CGBeginner 发表于 2012-10-25 01:17:13

Introduction to my galaxy engine 7: Volumetric Light Scattering

Introduction to my galaxy engine 7: Volumetric Light Scattering

花了一天时间,给引擎中添加了Volumetric Light Scattering模块.
视频地址:https://vimeo.com/43232452

截屏图如下:
http://pic002.cnblogs.com/images/2012/411346/2012060112065029.jpg
Volumetric Light Scattering又名god light,Crepuscular Rays 等等, 也是一个游戏中比较常见的效果,主要是用post process来实现的。
具体实现步骤如下:
1.渲染发光体和场景,场景不添加材质,只显示成黑色,将结果渲染到render target 1上。
http://pic002.cnblogs.com/images/2012/411346/2012060112100266.jpg
http://pic002.cnblogs.com/images/2012/411346/2012060112101352.jpg
2. 只渲染场景,添加材质和光照,将结果渲染到render target 2上。
3. 对render target 1 做采样处理,计算光照。原理见如下图:
http://pic002.cnblogs.com/images/2012/411346/2012060112135213.png
在屏幕上每一点到光源中心点做射线,对射线上点做采样。如果采样点被物体遮住,自然光照亮会减少。具体计算公式见GPU GERM 3相关那一张。最近处理结果如下图所示:
http://pic002.cnblogs.com/images/2012/411346/2012060112161023.jpg
4. 最后一步,将render target 2的贴图附在上图上,就是最后的结果了。
http://pic002.cnblogs.com/images/2012/411346/2012060112074267.jpg
完整代码如下:
1 SamplerState g_samWrap2 {3   Filter = MIN_MAG_MIP_LINEAR;4   AddressU = Wrap;5   AddressV = Wrap;6 };7 8 SamplerState g_samClamp9 { 10   Filter = MIN_MAG_MIP_LINEAR; 11   AddressU = Clamp; 12   AddressV = Clamp; 13 }; 14 15 DepthStencilState DisableDepth 16 { 17   DepthEnable = FALSE; 18   DepthWriteMask = ZERO; 19 }; 20 21 DepthStencilState EnableDepth 22 { 23   DepthEnable = TRUE; 24   DepthWriteMask = ALL; 25   DepthFunc = Less_Equal;//set to less equal since texture background is ini as 1.0 26 }; 27 28 BlendState NoBlending 29 { 30   AlphaToCoverageEnable = FALSE; 31   BlendEnable[0] = FALSE; 32 }; 33 34 BlendState AdditiveBlending 35 { 36   AlphaToCoverageEnable = FALSE; 37   BlendEnable[0] = TRUE; 38   SrcBlend = ONE; 39   DestBlend = ONE; 40   BlendOp = ADD; 41   SrcBlendAlpha = SRC_ALPHA; 42   DestBlendAlpha = INV_SRC_ALPHA; 43   RenderTargetWriteMask[0] = 0x0F; 44 }; 45 46 Texture2Dg_ModelTexture; 47 48 Texture2Dg_BlackSceneTexture; 49 Texture2Dg_NormalSceneTexture; 50 51 matrix g_World; 52 matrix g_View; 53 matrix g_Projection; 54 55 //float4 g_AmbientColor = float4(0.1f, 0.1f, 0.1f, 1.0f); 56 float4 g_DirLightColor = float4(0.3f, 0.3f, 0.3f, 1.0f); 57 float3 g_DirLightDir = float3(0.0f, 1.0f, -1.0f); 58 59 float4 g_LightPos = float4(0.0f, 1.0f, 0.0f, 1.0f); 60 uint NUM_SAMPLES = 200; 61 float g_Density = 1.0f; 62 float g_Weight = 1.0f; 63 float g_Decay = 0.98f; 64 float g_Exposure = 0.05f; 65 66 bool g_bLight; 67 68 struct VS_MODEL_INPUT 69 { 70     float4 Pos            : POSITION;          71     float2 Tex            : TEXCOORD0;    72     float3 Norm      : NORMAL;       73 }; 74 75 struct PS_MODEL_INPUT 76 { 77     float4 Pos            : SV_POSITION;    78     float2 Tex            : TEXCOORD0;    79     float3 Norm      : NORMAL;    80 }; 81 82 struct PS_MODEL_OUTPUT 83 { 84     float4 blackScene      : SV_Target0; 85     float4 normalScene      : SV_Target1; 86 }; 87 //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 88 struct VS_QUAD_INPUT 89 { 90     float4 Pos            : POSITION;          91     float2 Tex            : TEXCOORD0;       92 }; 93 94 struct PS_SCENE_INPUT 95 { 96     float4 Pos                        : SV_POSITION;    97     float2 Tex                        : TEXCOORD0;    98     float2 ScreenLightPos      : TEXCOORD1; 99 };100 //---------------------------------------------------------------------------------------render black scene--------------------------------------------------------------------------------------------------------101 PS_MODEL_INPUT VS_SCENE(VS_MODEL_INPUT input)102 {103   PS_MODEL_INPUT output = (PS_MODEL_INPUT)0;104   output.Pos = input.Pos;105   output.Pos.w = 1;106 107   output.Pos = mul( output.Pos, g_World );108   output.Pos = mul( output.Pos, g_View );109   output.Pos = mul( output.Pos, g_Projection );110   output.Pos = output.Pos / output.Pos.w;111 112   output.Norm = input.Norm;113   output.Tex = input.Tex;114   return output;115 }116 117 PS_MODEL_OUTPUT PS_BLACK_SCENE(PS_MODEL_INPUT input)118 {119   PS_MODEL_OUTPUT output = (PS_MODEL_OUTPUT)0;120 121   if(g_bLight)122     {123         output.blackScene = float4(1.0f, 1.0f, 1.0f, 1.0f);124         output.normalScene = float4(0.0f, 0.0f, 0.0f, 0.0f);125     }126   else127     {128         output.blackScene = float4(0.0f, 0.0f, 0.0f, 1.0f);129         output.normalScene = dot(normalize(g_DirLightDir), input.Norm) * g_DirLightColor * g_ModelTexture.Sample( g_samWrap, input.Tex );130         output.normalScene.a = 1;131     }132 133   return output;134 }135 136 PS_SCENE_INPUT VS_VLS(VS_QUAD_INPUT input)137 {138   PS_SCENE_INPUT output = (PS_SCENE_INPUT)0;139 140   float2 Pos = input.Pos.xy;141   output.Pos = float4(Pos.xy, 0, 1);142   143   output.Tex =0.5 * (1 + Pos);144 145   float4 ScreenLightPos = g_LightPos;146   ScreenLightPos = mul( ScreenLightPos, g_World );147   ScreenLightPos = mul( ScreenLightPos, g_View );148   ScreenLightPos = mul( ScreenLightPos, g_Projection );149   ScreenLightPos = ScreenLightPos / ScreenLightPos.w;150   ScreenLightPos = (ScreenLightPos + 1.0f) / 2.0f;151   output.ScreenLightPos = ScreenLightPos;152 153   return output;154 }155 156 float4 PS_VLS(PS_SCENE_INPUT input) : SV_Target157 {158   float2 texCoord = input.Tex;159 160   float2 deltaTexCoord = (texCoord - input.ScreenLightPos); 161   deltaTexCoord *= 1.0f / NUM_SAMPLES * g_Density;162 163   float4 color = g_BlackSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y));164 165   float illuminationDecay = 1.0f;166 167   for (uint i = 0; i < NUM_SAMPLES; i++)168     {169         texCoord -= deltaTexCoord;170         float4 sampleColor = g_BlackSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y));//shift y after operation171         sampleColor *= illuminationDecay * g_Weight;172         color += sampleColor;173         illuminationDecay *= g_Decay;174     }175 176   color *= g_Exposure;177   color.a = 1;178   return color;179 }180 181 float4 PS_Blend(PS_SCENE_INPUT input) : SV_Target182 {183   float2 texCoord = input.Tex;184   return g_NormalSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y));185 }186 187 technique10 RenderBlackScene188 {189     pass p0190     {191       SetVertexShader( CompileShader( vs_4_0, VS_SCENE() ) );192       SetGeometryShader( NULL );193       SetPixelShader( CompileShader( ps_4_0, PS_BLACK_SCENE() ) );194 195         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );196     }197 }198 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------199 technique10 VLS200 {201     pass p0202     {203       SetVertexShader( CompileShader( vs_4_0, VS_VLS() ) );204       SetGeometryShader( NULL );205       SetPixelShader( CompileShader( ps_4_0, PS_VLS() ) );206 207         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );208     }209 }210 211 technique10 BlendScene212 {213     pass p0214     {215       SetVertexShader( CompileShader( vs_4_0, VS_VLS() ) );216       SetGeometryShader( NULL );217       SetPixelShader( CompileShader( ps_4_0, PS_Blend() ) );218 219         SetBlendState( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );220         SetDepthStencilState( EnableDepth, 0 );//set depth test to less_equal221     }222 }
页: [1]
查看完整版本: Introduction to my galaxy engine 7: Volumetric Light Scattering