Introduction to my galaxy engine 4: Test on local light model

今天按照shadow volumn阴影的检查方法对spot light和point light的灯光范围模型做了个测试。

测试图片如下:(蓝色为场景中的物体,黄色表示场景中受灯光影响的部分,绿色为灯光模型)

depth fail test 和 stencil test 是在GPU中执行的,首先渲染蓝色的盒子RenderScene,再渲染灯光模型CalRadium(disable write to depth buffer),最后再将模板值为1的部分添加上另一个颜色来突出受光照部分LitScene,代码如下:

  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 AlphaBlendingOn
 35 {
 36     BlendEnable[0] = TRUE;
 37     SrcBlend = SRC_ALPHA;
 38     DestBlend = INV_SRC_ALPHA;
 39 };
 40 
 41 BlendState AdditiveBlending
 42 {
 43     AlphaToCoverageEnable = FALSE;
 44     BlendEnable[0] = TRUE;
 45     SrcBlend = ONE;
 46     DestBlend = ONE;
 47     BlendOp = ADD;
 48     SrcBlendAlpha = ZERO;
 49     DestBlendAlpha = ZERO;
 50     BlendOpAlpha = ADD;
 51     RenderTargetWriteMask[0] = 0x0F;
 52 };
 53 
 54 RasterizerState DisableCulling
 55 {
 56     //FillMode = WIREFRAME;
 57     CullMode = NONE;
 58 };
 59 
 60 RasterizerState EnableCulling
 61 {
 62     //FillMode = WIREFRAME;
 63     CullMode = BACK;
 64 };
 65 
 66 RasterizerState FrontCulling
 67 {
 68     //FillMode = WIREFRAME;
 69     CullMode = FRONT;
 70 };
 71 
 72 BlendState DisableFrameBuffer
 73 {
 74     BlendEnable[0] = FALSE;
 75     RenderTargetWriteMask[0] = 0x0;
 76 };
 77 
 78 BlendState EnableFrameBuffer
 79 {
 80     BlendEnable[0] = FALSE;
 81     RenderTargetWriteMask[0] = 0x0F;
 82 };
 83 
 84 DepthStencilState TwoSidedStencil
 85 {
 86     DepthEnable = true;
 87     DepthWriteMask = ZERO;//Turn off writes to the depth-stencil buffer.
 88     DepthFunc = Less;
 89     
 90     // Setup stencil states
 91     StencilEnable = true;
 92     StencilReadMask = 0xFFFFFFFF;
 93     StencilWriteMask = 0xFFFFFFFF;
 94     
 95     BackFaceStencilFunc = Always;// how stencil data is compared against existing stencil data.Always pass the comparison.
 96     BackFaceStencilDepthFail = Incr;// describes the stencil operation to perform when stencil testing passes and depth testing fails. 
 97     BackFaceStencilPass = Keep;// describes the stencil operation to perform when stencil testing and depth testing both pass. 
 98     BackFaceStencilFail = Keep;//describes the stencil operation to perform when stencil testing fails. 
 99     
100     FrontFaceStencilFunc = Always;
101     FrontFaceStencilDepthFail = Decr;
102     FrontFaceStencilPass = Keep;
103     FrontFaceStencilFail = Keep;
104 };
105 
106 DepthStencilState RenderNonShadows
107 {
108     DepthEnable = true;
109     DepthWriteMask = ZERO;
110     DepthFunc = Less_Equal;
111     
112     StencilEnable = true;
113     StencilReadMask = 0xFFFFFFFF;//read stencil buffer to check if lit or not
114     StencilWriteMask = 0x0;
115     
116     FrontFaceStencilFunc = Less_Equal;//If the source data is greater (multipay light)or equal to the destination data, the comparison passes.
117     FrontFaceStencilPass = Keep;//Keep the existing stencil data.
118     FrontFaceStencilFail = Zero;//Set the stencil data to 0.
119     
120     BackFaceStencilFunc = Never;//Never pass the comparison.
121     BackFaceStencilPass = Zero;
122     BackFaceStencilFail = Zero;
123 };
124 
125 Texture2D  g_ModelTexture;
126 
127 Texture2D  g_NormDepthTexture;
128 Texture2D  g_DiffuseTexture;
129 
130 matrix World;
131 matrix View;
132 matrix Projection;
133 
134 float4 g_AmbientColor = float4(0.1f, 0.1f, 0.1f, 1.0f);
135 float4 g_DirLightColor = float4(0.3f, 0.3f, 0.3f, 1.0f);
136 float3 g_DirLightDir = float3(0.0f, 1.0f, -1.0f);
137 float4 g_LocalLightColor;
138 //---------------------------------------------------------------------------------------------------------------------------------
139 struct VS_MODEL_INPUT
140 {
141     float4 Pos            : POSITION;         
142     float2 Tex            : TEXCOORD0;     
143     float3 Norm        : NORMAL;       
144 };
145 
146 struct PS_MODEL_INPUT
147 {
148     float4 Pos            :SV_POSITION;   
149     float2 Tex            : TEXCOORD0;     
150     float3 Norm        : TEXCOORD1;    
151 };
152 
153 struct PS_MODEL_OUTPUT
154 {
155     float4 NormDepth    : SV_Target0;
156     float4 DiffuseColor    : SV_Target1;
157 };
158 //------------------------------------------------------------------------------------------------------------------------
159 struct VS_QUAD_INPUT
160 {
161     float4 Pos            :POSITION;           
162     float2 Tex            : TEXCOORD0;       
163 };
164 
165 struct PS_SCENE_INPUT
166 {
167     float4 Pos            :SV_POSITION;   
168     float2 Tex            : TEXCOORD0;     
169 };
170 
171 struct PS_SCENE_OUTPUT
172 {
173     float4 Color        :SV_Target;   
174     float     Depth        : SV_Depth;
175 };
176 //-----------------------------------------------------------render scene to gbuffer-----------------------------------------------
177 PS_MODEL_INPUT VS_SCENE(VS_MODEL_INPUT input)
178 {
179     PS_MODEL_INPUT output = (PS_MODEL_INPUT)0;
180     output.Pos = input.Pos;
181     output.Pos.w = 1;
182 
183     output.Pos = mul( output.Pos, World );
184     output.Pos = mul( output.Pos, View );
185     output.Pos = mul( output.Pos, Projection );
186     output.Pos = output.Pos / output.Pos.w;
187 
188     output.Norm = input.Norm;
189     output.Tex = input.Tex;
190     return output;
191 }
192 
193 PS_MODEL_OUTPUT PS_SCENE(PS_MODEL_INPUT input)
194 {
195     PS_MODEL_OUTPUT output = (PS_MODEL_OUTPUT)0;
196 
197     float4 NormDepth = 0;
198     NormDepth.rgb = input.Norm;//normal
199     NormDepth.a = input.Pos.z;//depth
200 
201     output.NormDepth = NormDepth;
202     output.DiffuseColor = g_ModelTexture.Sample( g_samWrap, input.Tex );
203 
204     return output;
205 }
206 //----------------------------------------------add ambient light to scene------------------------------------------------
207 PS_SCENE_INPUT VS_Ambient(VS_QUAD_INPUT input)
208 {
209     PS_SCENE_INPUT output = (PS_SCENE_INPUT)0;
210 
211     float2 Pos = input.Pos.xy;
212     output.Pos = float4(Pos.xy, 0, 1);
213     
214     output.Tex.x = 0.5 * (1 + Pos.x);
215     output.Tex.y = 0.5 * (1 - Pos.y);
216 
217     return output;
218 }
219 
220 PS_SCENE_OUTPUT PS_Ambient(PS_SCENE_INPUT input)
221 {
222     PS_SCENE_OUTPUT output = (PS_SCENE_OUTPUT)0;
223 
224     float4 DiffuseColor = g_DiffuseTexture.Sample( g_samClamp, input.Tex );
225     float4 NormalDepth = g_NormDepthTexture.Sample( g_samClamp, input.Tex );
226     float3 Normal = NormalDepth.rgb;
227     float Depth = NormalDepth.a;
228     float4 Pos = input.Pos;
229 
230     clip(Depth - 0.0001);
231 
232     output.Color = (g_AmbientColor + dot(normalize(g_DirLightDir), Normal) * g_DirLightColor) * DiffuseColor;
233     output.Color.a = 1;
234     output.Depth = Depth;
235     
236     return output;
237 }
238 //------------------------------calcuate depth test and set stencil value-------------------------------------------------------
239 float4 PS_CalRadium(PS_MODEL_INPUT input) : SV_Target
240 {   
241     return float4(0.0, 1.0, 0.0, 0.3);//green light volumn
242 }
243 //-------------------------------------------------------------------------------------lit the area where stencil value is 1----------------------------------------------------------------------------------------
244 float4 PS_LitScene(PS_SCENE_INPUT input) : SV_Target
245 {
246     return g_LocalLightColor;
247 }
248 //---------------------------------------------------------------------------------------------------------
249 technique10 RenderScene
250 {
251     pass p0
252     {
253         SetVertexShader( CompileShader( vs_4_0, VS_SCENE() ) );
254         SetGeometryShader( NULL );
255         SetPixelShader( CompileShader( ps_4_0, PS_SCENE() ) );
256 
257         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
258         SetDepthStencilState( EnableDepth, 0 );
259         SetRasterizerState( EnableCulling );
260 
261         //SetRasterizerState( FrontCulling );
262     }  
263 }
264 
265 technique10 AmbientLighting
266 {
267     pass p0
268     {
269         SetVertexShader( CompileShader( vs_4_0, VS_Ambient() ) );
270         SetGeometryShader( NULL );
271         SetPixelShader( CompileShader( ps_4_0, PS_Ambient() ) );
272 
273         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
274         SetDepthStencilState( EnableDepth, 0 );//render all model on texture, no depth test is needed
275         SetRasterizerState( EnableCulling );
276     }  
277 }
278 
279 technique10 CalRadium
280 {
281     pass p0
282     {
283         SetVertexShader( CompileShader( vs_4_0, VS_SCENE() ) );
284         SetGeometryShader( NULL );
285         SetPixelShader( CompileShader( ps_4_0, PS_CalRadium() ) );
286 
287         SetBlendState( AlphaBlendingOn, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
288         //SetBlendState( DisableFrameBuffer, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );//don't render color to render target
289         SetDepthStencilState( TwoSidedStencil, 1 ); //do depth fail test, write to stencil buffer
290         SetRasterizerState( DisableCulling );//no culling, so both front and back face could be tested
291     }  
292 }
293 
294 technique10 LitScene
295 {
296     pass p0
297     {
298         SetVertexShader( CompileShader( vs_4_0, VS_Ambient() ) );
299         SetGeometryShader( NULL );
300         SetPixelShader( CompileShader( ps_4_0, PS_LitScene() ) );
301 
302         SetBlendState( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
303         SetDepthStencilState( RenderNonShadows, 1); //when stencil value is 0, stencil fun pass and lit that pixel
304         SetRasterizerState( EnableCulling );
305     }  
306 }
原文地址:https://www.cnblogs.com/RobinG/p/2517404.html