// Soft shadow with shadow accumulation // SHADOWMAP generation //----------------------------------------------------------------------------- // Vertex Shader: RenderShadowMap_07_VS // Desc: Process vertex for the shadow map //----------------------------------------------------------------------------- void RenderShadowMap_07_VS( float4 Position : POSITION, out float4 ldPosition : POSITION, out float zcam : TEXCOORD0 ) { ldPosition = mul( Position, WorldLightProj ); // Compute the projected coordinates zcam = ldPosition.w; // Store light's camera z } //----------------------------------------------------------------------------- // Pixel Shader: RenderShadowMap_07_PS // Desc: Process pixel for the shadow map //----------------------------------------------------------------------------- float4 RenderShadowMap_07_PS( float zcam : TEXCOORD0 ):COLOR { return float4(zcam,0,0,0); } // SCENE RENDERING //----------------------------------------------------------------------------- // Vertex Shader: RenderSceneWithTechnique_07_VS // Desc: Process vertex for scene //----------------------------------------------------------------------------- VS_OUTPUT RenderSceneWithTechnique_07_VS( VS_INPUT IN ) { VS_OUTPUT OUT = (VS_OUTPUT)0; OUT.Color = IN.Color; OUT.Tex = IN.Tex; // transform model-space vertex position to light's camera space: OUT.ldPosition = mul(IN.Position, WorldLightProj); OUT.lcPosition = mul(IN.Position, WorldLight); // transform model-space vertex position to normalized screen space: OUT.hPosition = mul(IN.Position, WorldViewProj); return OUT; } //----------------------------------------------------------------------------- // Pixel Shader: RenderSceneWithTechnique_07_PS // Desc: shadow accumulation //----------------------------------------------------------------------------- float4 RenderSceneWithTechnique_07_PS( VS_OUTPUT IN) : COLOR { half R = max( g_fLightSize, 0.1h ); g_fBiasSlope = max( g_fBiasSlope, 0.1h ); half m = R; half mapsize = 2 * m * tan( g_fFov / 2.0h ); // size of half shadow map in world space half Deltal = mapsize / SHADOWMAP_SIZE; // size of a lexel edge in world space half step = R / g_iKernelSize; half3 r = IN.lcPosition; // shaded point in light's camera space half RR = R * (r.z-m)/r.z; // directional set in which the light is seen from the shaded point half RR2 = RR * RR; half2 q = r.xy / r.z * m; // projection of r onto the shadow plane half2 quv = q / mapsize; quv = half2( ( 0.5 + quv.x ), ( 0.5 - quv.y ) ); // r in texture coordinates half shadow = 0; for ( int i = 0; i < g_iKernelSize; i++ ) { for ( int j = 0; j < g_iKernelSize; j++ ) { half2 uvoffset = half2( i - g_iKernelSize / 2.0f, j - g_iKernelSize / 2.0f ) / SHADOWMAP_SIZE * step; half2 l = q + half2( uvoffset.x, -uvoffset.y ) * mapsize; half cz = tex2D( g_ShadowMapColorSampler, quv + uvoffset ).x; half size = (r.z - m)/(r.z - cz) * cz / m; half2 lc = (m - cz)/(r.z - cz) * r.xy + size * l.xy; if( cz < r.z - g_fShadowBias * 10.0f && dot(lc - q, lc - q) < RR2 + g_fBiasSlope ) { shadow += size * size; } } } shadow *= Deltal * Deltal * step * step / RR2; return tex2D( g_samScene, IN.Tex ) * ( 1 - shadow * g_fIntensity * g_fIntensity ) * g_vMaterial; } // TECHNIQUE //----------------------------------------------------------------------------- // Techniques: RenderShadowMap // Desc: Render the shadow map //----------------------------------------------------------------------------- technique RenderShadowMap_7 { pass p0 { VertexShader = compile vs_2_0 RenderShadowMap_07_VS(); PixelShader = compile ps_2_0 RenderShadowMap_07_PS(); } } technique RenderSceneWithTechnique_7 { pass p0 { VertexShader = compile vs_2_0 RenderSceneWithTechnique_07_VS(); PixelShader = compile ps_3_0 RenderSceneWithTechnique_07_PS(); } }