source: GTP/trunk/App/Demos/Illum/SoftShadowMap/Shaders/technique_06.fx @ 1637

Revision 1637, 7.1 KB checked in by szirmay, 18 years ago (diff)
Line 
1// Percentage closer soft shadows
2// nVidia implementation
3
4
5// SHADOWMAP generation
6
7//-----------------------------------------------------------------------------
8// Vertex Shader: RenderShadowMap_06_VS
9// Desc: Process vertex for the shadow map
10//-----------------------------------------------------------------------------
11void RenderShadowMap_06_VS(
12                float4 Pos  : POSITION,
13    out float4 oPos : POSITION,
14    out float  hPos : TEXCOORD0 )
15{
16        oPos = mul( Pos, WorldLightProj );      // Compute the projected coordinates
17    hPos = oPos.w;                                              // Store z in our spare texcoord
18}
19
20//-----------------------------------------------------------------------------
21// Pixel Shader: RenderShadowMap_06_PS
22// Desc: Process pixel for the shadow map
23//-----------------------------------------------------------------------------
24float4 RenderShadowMap_06_PS(
25                float hPos : TEXCOORD0 ):COLOR
26{
27        return float4(hPos,0,0,0);
28}
29
30
31// SCENE RENDERING
32
33//-----------------------------------------------------------------------------
34// Vertex Shader: RenderSceneWithTechnique_06_VS
35// Desc: Process vertex for scene
36//-----------------------------------------------------------------------------
37VS_OUTPUT RenderSceneWithTechnique_06_VS( VS_INPUT IN )
38{
39        VS_OUTPUT OUT = (VS_OUTPUT)0;
40        OUT.Color = IN.Color;
41        OUT.Tex = IN.Tex;
42
43        // transform model-space vertex position to light's normalized device space:
44        OUT.ldPosition = mul(IN.Position, WorldLightProj);
45
46        // transform model-space vertex position to normalized screen space:
47        OUT.hPosition = mul(IN.Position, WorldViewProj);
48        return OUT;
49}
50
51
52//-----------------------------------------------------------------------------
53// Pixel Shader: RenderSceneWithTechnique_06_PS
54// Desc: PCF soft shadow
55//-----------------------------------------------------------------------------
56// -------------------------------------
57// STEP 1: Search for potential blockers
58// -------------------------------------
59half findBlocker(
60                half2 uv,
61                half4 LP,
62        half searchWidth )
63{
64        // divide filter width by number of samples to use
65        half stepSize = 2 * searchWidth / g_iKernelSize;
66
67        // compute starting point uv coordinates for search
68        uv = uv - half2(searchWidth, searchWidth);
69
70        // reset sum to zero
71        half blockerSum = 0;
72        half receiver = LP.z;
73        half blockerCount = 0;
74        half foundBlocker = 0;
75
76        // iterate through search region and add up depth values
77        for (int i=0; i<g_iKernelSize; i++) {
78               for (int j=0; j<g_iKernelSize; j++) {
79                       half shadMapDepth = tex2D(g_ShadowMapColorSampler, uv + half2(i*stepSize,j*stepSize)).x;
80                       // found a blocker
81                       if (shadMapDepth < receiver) {
82                               blockerSum += shadMapDepth;
83                               blockerCount++;
84                               foundBlocker = 1;
85                       }
86               }
87        }
88
89                half result;
90               
91                if (foundBlocker == 0) {
92                        // set it to a unique number so we can check
93                        // later to see if there was no blocker
94                        result = 999;
95                }
96                else {
97                    // return average depth of the blockers
98                        result = blockerSum / blockerCount;
99                }
100               
101                return result;
102}
103
104// ------------------------------------------------
105// STEP 2: Estimate penumbra based on
106// blocker estimate, receiver depth, and light size
107// ------------------------------------------------
108half estimatePenumbra(
109                half receiver,      // receiver depth
110                half blocker )
111{
112       // estimate penumbra using parallel planes approximation
113       return (receiver - blocker) * g_fLightSize / blocker;
114}
115
116// ----------------------------------------------------
117// Step 3: Percentage-closer filter implementation with
118// variable filter width and number of samples.
119// This assumes a square filter with the same number of
120// horizontal and vertical samples.
121// ----------------------------------------------------
122
123half PCF_Filter(
124                half2 uv,
125                half4 LP,
126        half filterWidth )
127{
128       // compute step size for iterating through the kernel
129       half stepSize = 2 * filterWidth / g_iKernelSize;
130
131       // compute uv coordinates for upper-left corner of the kernel
132       uv = uv - half2(filterWidth,filterWidth);
133
134       half sum = 0;  // sum of successful depth tests
135
136       // now iterate through the kernel and filter
137       for (int i=0; i<g_iKernelSize; i++) {
138           for (int j=0; j<g_iKernelSize; j++) {
139               // get depth at current texel of the shadow map
140               half shadMapDepth = 0;
141               
142               shadMapDepth = tex2D(g_ShadowMapColorSampler, uv + half2(i*stepSize,j*stepSize)).x;
143
144               // test if the depth in the shadow map is closer than
145               // the eye-view point
146               half shad = LP.z < shadMapDepth;
147
148               // accumulate result
149               sum += shad;
150           }
151       }
152       
153       // return average of the samples
154       return sum / (g_iKernelSize*g_iKernelSize);
155}
156
157
158float4 RenderSceneWithTechnique_06_PS( VS_OUTPUT IN ) : COLOR
159{
160        // Apply bias
161        IN.ldPosition.z -= g_fShadowBias;
162       
163        // The soft shadow algorithm follows:
164
165   // Compute uv coordinates for the point being shaded
166   // Saves some future recomputation.
167   half2 uv = half2(.5,-.5)*(IN.ldPosition.xy)/IN.ldPosition.w + half2( 0.5f + HALF_TEXEL, 0.5f + HALF_TEXEL );
168
169   // ---------------------------------------------------------
170   // Step 1: Find blocker estimate
171   half blocker = findBlocker(uv, IN.ldPosition, g_fIntensity * g_fLightSize / IN.ldPosition.z );
172   
173   // ---------------------------------------------------------
174   // Step 2: Estimate penumbra using parallel planes approximation
175   half penumbra = estimatePenumbra( IN.ldPosition.z, blocker );
176
177   // ---------------------------------------------------------
178   // Step 3: Compute percentage-closer filter
179   // based on penumbra estimate
180
181   // Now do a penumbra-based percentage-closer filter
182   half shadowed = PCF_Filter(uv, IN.ldPosition, penumbra );
183   
184   // If no blocker was found, just return 1.0
185   // since the point isn't occluded
186   if (blocker > 998)
187                shadowed = 1.0;
188
189   // Visualize lighting and shadows
190   if( shadowed < 1.0 )
191   {
192                shadowed *= g_fBiasSlope;
193                if( shadowed > 1.0 )
194                {
195                        shadowed = 1.0;
196                }
197   }
198   return tex2D(g_samScene, IN.Tex) * shadowed  * g_vMaterial;
199}
200
201
202
203// TECHNIQUE
204
205//-----------------------------------------------------------------------------
206// Techniques: RenderShadowMap
207// Desc: Render the shadow map
208//-----------------------------------------------------------------------------
209
210technique RenderShadowMap_6
211{
212    pass p0
213    {
214        VertexShader = compile vs_2_0 RenderShadowMap_06_VS();
215        PixelShader  = compile ps_2_0 RenderShadowMap_06_PS();
216    }
217}
218
219
220technique RenderSceneWithTechnique_6
221{
222    pass p0
223    {
224        VertexShader = compile vs_2_0 RenderSceneWithTechnique_06_VS();
225        PixelShader  = compile ps_3_0 RenderSceneWithTechnique_06_PS();
226    }
227}
Note: See TracBrowser for help on using the repository browser.