Introduction to my galaxy engine 7: Volumetric Light Scattering
花了一天时间,给引擎中添加了Volumetric Light Scattering模块.
视频地址:https://vimeo.com/43232452
截屏图如下:
Volumetric Light Scattering又名god light,Crepuscular Rays 等等, 也是一个游戏中比较常见的效果,主要是用post process来实现的。
具体实现步骤如下:
1.渲染发光体和场景,场景不添加材质,只显示成黑色,将结果渲染到render target 1上。
2. 只渲染场景,添加材质和光照,将结果渲染到render target 2上。
3. 对render target 1 做采样处理,计算光照。原理见如下图:
在屏幕上每一点到光源中心点做射线,对射线上点做采样。如果采样点被物体遮住,自然光照亮会减少。具体计算公式见GPU GERM 3相关那一张。最近处理结果如下图所示:
4. 最后一步,将render target 2的贴图附在上图上,就是最后的结果了。
完整代码如下:
1 SamplerState g_samWrap 2 { 3 Filter = MIN_MAG_MIP_LINEAR; 4 AddressU = Wrap; 5 AddressV = Wrap; 6 }; 7 8 SamplerState g_samClamp 9 { 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 Texture2D g_ModelTexture; 47 48 Texture2D g_BlackSceneTexture; 49 Texture2D g_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 else 127 { 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_Target 157 { 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 operation 171 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_Target 182 { 183 float2 texCoord = input.Tex; 184 return g_NormalSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y)); 185 } 186 187 technique10 RenderBlackScene 188 { 189 pass p0 190 { 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 VLS 200 { 201 pass p0 202 { 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 BlendScene 212 { 213 pass p0 214 { 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_equal 221 } 222 }
References:
[1] http://www.unrealcreations.com/groups/kb/wiki/7d174/Volumetric_Light_Scattering_Implementation.html
posted on 2012-06-01 12:35 CGBeginner 阅读(1000) 评论(0) 编辑 收藏 举报