Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutorial/Tutorial/Media/materials/programs/DepthShadowmap.hlsl @ 41

Last change on this file since 41 was 25, checked in by nicolasc, 17 years ago

added Media and Config

File size: 8.5 KB
Line 
1/* This file implements standard programs for depth shadow mapping.
2   These particular ones are suitable for additive lighting models, and
3   include 3 techniques to reduce depth fighting on self-shadowed surfaces,
4   constant bias, gradient (slope-scale) bias, and a fuzzy shadow map comparison*/
5
6
7// Shadow caster vertex program.
8void casterVP(
9        float4 position                 : POSITION,
10        out float4 outPos               : POSITION,
11        out float2 outDepth             : TEXCOORD0,
12
13        uniform float4x4 worldViewProj,
14        uniform float4 texelOffsets,
15        uniform float4 depthRange
16        )
17{
18        outPos = mul(worldViewProj, position);
19
20        // fix pixel / texel alignment
21        outPos.xy += texelOffsets.zw * outPos.w;
22        // linear depth storage
23        // offset / scale range output
24#if LINEAR_RANGE
25        outDepth.x = (outPos.z - depthRange.x) * depthRange.w;
26#else
27        outDepth.x = outPos.z;
28#endif
29        outDepth.y = outPos.w;
30}
31
32
33// Shadow caster fragment program for high-precision single-channel textures   
34void casterFP(
35        float2 depth                    : TEXCOORD0,
36        out float4 result               : COLOR)
37       
38{
39#if LINEAR_RANGE
40        float finalDepth = depth.x;
41#else
42        float finalDepth = depth.x / depth.y;
43#endif
44        // just smear across all components
45        // therefore this one needs high individual channel precision
46        result = float4(finalDepth, finalDepth, finalDepth, 1);
47}
48
49
50       
51void receiverVP(
52        float4 position         : POSITION,
53        float4 normal           : NORMAL,
54
55        out float4 outPos                       : POSITION,
56        out float4 outColour            : COLOR,
57        out float4 outShadowUV          : TEXCOORD0,
58
59        uniform float4x4 world,
60        uniform float4x4 worldIT,
61        uniform float4x4 worldViewProj,
62        uniform float4x4 texViewProj,
63        uniform float4 lightPosition,
64        uniform float4 lightColour,
65        uniform float4 shadowDepthRange
66        )
67{
68        float4 worldPos = mul(world, position);
69        outPos = mul(worldViewProj, position);
70
71        float3 worldNorm = mul(worldIT, normal).xyz;
72
73        // calculate lighting (simple vertex lighting)
74        float3 lightDir = normalize(
75                lightPosition.xyz -  (worldPos.xyz * lightPosition.w));
76
77        outColour = lightColour * max(dot(lightDir, worldNorm), 0.0);
78
79        // calculate shadow map coords
80        outShadowUV = mul(texViewProj, worldPos);
81#if LINEAR_RANGE
82        // adjust by fixed depth bias, rescale into range
83        outShadowUV.z = (outShadowUV.z - shadowDepthRange.x) * shadowDepthRange.w;
84#endif
85       
86
87
88       
89}
90
91void receiverFP(
92        float4 position                 : POSITION,
93        float4 shadowUV                 : TEXCOORD0,
94        float4 vertexColour             : COLOR,
95
96        uniform sampler2D shadowMap : register(s0),
97        uniform float inverseShadowmapSize,
98        uniform float fixedDepthBias,
99        uniform float gradientClamp,
100        uniform float gradientScaleBias,
101        uniform float shadowFuzzyWidth,
102       
103        out float4 result               : COLOR)
104{
105        // point on shadowmap
106#if LINEAR_RANGE
107        shadowUV.xy = shadowUV.xy / shadowUV.w;
108#else
109        shadowUV = shadowUV / shadowUV.w;
110#endif
111        float centerdepth = tex2D(shadowMap, shadowUV.xy).x;
112   
113    // gradient calculation
114        float pixeloffset = inverseShadowmapSize;
115    float4 depths = float4(
116        tex2D(shadowMap, shadowUV.xy + float2(-pixeloffset, 0)).x,
117        tex2D(shadowMap, shadowUV.xy + float2(+pixeloffset, 0)).x,
118        tex2D(shadowMap, shadowUV.xy + float2(0, -pixeloffset)).x,
119        tex2D(shadowMap, shadowUV.xy + float2(0, +pixeloffset)).x);
120
121        float2 differences = abs( depths.yw - depths.xz );
122        float gradient = min(gradientClamp, max(differences.x, differences.y));
123        float gradientFactor = gradient * gradientScaleBias;
124
125        // visibility function
126        float depthAdjust = gradientFactor + (fixedDepthBias * centerdepth);
127        float finalCenterDepth = centerdepth + depthAdjust;
128
129        // shadowUV.z contains lightspace position of current object
130
131#if FUZZY_TEST
132        // fuzzy test - introduces some ghosting in result and doesn't appear to be needed?
133        //float visibility = saturate(1 + delta_z / (gradient * shadowFuzzyWidth));
134        float visibility = saturate(1 + (finalCenterDepth - shadowUV.z) * shadowFuzzyWidth * shadowUV.w);
135
136        result = vertexColour * visibility;
137#else
138        // hard test
139#if PCF
140        // use depths from prev, calculate diff
141        depths += depthAdjust.xxxx;
142        float final = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
143        final += (depths.x > shadowUV.z) ? 1.0f : 0.0f;
144        final += (depths.y > shadowUV.z) ? 1.0f : 0.0f;
145        final += (depths.z > shadowUV.z) ? 1.0f : 0.0f;
146        final += (depths.w > shadowUV.z) ? 1.0f : 0.0f;
147       
148        final *= 0.2f;
149
150        result = float4(vertexColour.xyz * final, 1);
151       
152#else
153        result = (finalCenterDepth > shadowUV.z) ? vertexColour : float4(0,0,0,1);
154#endif
155
156#endif
157   
158
159       
160}
161
162
163
164
165// Expand a range-compressed vector
166float3 expand(float3 v)
167{
168        return (v - 0.5) * 2;
169}
170
171
172/* Normal mapping plus depth shadowmapping receiver programs
173*/
174void normalMapShadowReceiverVp(float4 position  : POSITION,
175                         float3 normal          : NORMAL,
176                         float2 uv                      : TEXCOORD0,
177                         float3 tangent     : TANGENT0,
178                         
179                         // outputs
180                         out float4 outPos       : POSITION,
181                         out float4 outShadowUV  : TEXCOORD0,
182                         out float2 oUv                  : TEXCOORD1,
183                         out float3 oTSLightDir  : TEXCOORD2,
184                         // parameters
185                         uniform float4 lightPosition, // object space
186                         uniform float4x4 world,
187                         uniform float4x4 worldViewProj,
188                         uniform float4x4 texViewProj)
189{
190        float4 worldPos = mul(world, position);
191        outPos = mul(worldViewProj, position);
192
193        // calculate shadow map coords
194        outShadowUV = mul(texViewProj, worldPos);
195#if LINEAR_RANGE
196        // adjust by fixed depth bias, rescale into range
197        outShadowUV.z = (outShadowUV.z - shadowDepthRange.x) * shadowDepthRange.w;
198#endif
199       
200        // pass the main uvs straight through unchanged
201        oUv = uv;
202
203        // calculate tangent space light vector
204        // Get object space light direction
205        // Non-normalised since we'll do that in the fragment program anyway
206        float3 lightDir = lightPosition.xyz -  (position * lightPosition.w);
207
208        // Calculate the binormal (NB we assume both normal and tangent are
209        // already normalised)
210        // NB looks like nvidia cross params are BACKWARDS to what you'd expect
211        // this equates to NxT, not TxN
212        float3 binormal = cross(tangent, normal);
213       
214        // Form a rotation matrix out of the vectors
215        float3x3 rotation = float3x3(tangent, binormal, normal);
216       
217        // Transform the light vector according to this matrix
218        oTSLightDir = mul(rotation, lightDir);
219
220       
221}
222
223
224void normalMapShadowReceiverFp(
225                          float4 shadowUV       : TEXCOORD0,
226                          float2 uv                     : TEXCOORD1,
227                          float3 TSlightDir : TEXCOORD2,
228
229                          out float4 result     : COLOR,
230
231                          uniform float4 lightColour,
232                          uniform float inverseShadowmapSize,
233                          uniform float fixedDepthBias,
234                          uniform float gradientClamp,
235                          uniform float gradientScaleBias,
236                          uniform float shadowFuzzyWidth,
237                         
238                          uniform sampler2D   shadowMap : register(s0),
239                          uniform sampler2D   normalMap : register(s1),
240                          uniform samplerCUBE normalCubeMap : register(s2))
241{
242
243        // retrieve normalised light vector, expand from range-compressed
244        float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);
245
246        // get bump map vector, again expand from range-compressed
247        float3 bumpVec = expand(tex2D(normalMap, uv).xyz);
248
249        // Calculate dot product
250        float4 vertexColour = lightColour * dot(bumpVec, lightVec);
251
252
253        // point on shadowmap
254#if LINEAR_RANGE
255        shadowUV.xy = shadowUV.xy / shadowUV.w;
256#else
257        shadowUV = shadowUV / shadowUV.w;
258#endif
259        float centerdepth = tex2D(shadowMap, shadowUV.xy).x;
260   
261    // gradient calculation
262        float pixeloffset = inverseShadowmapSize;
263    float4 depths = float4(
264        tex2D(shadowMap, shadowUV.xy + float2(-pixeloffset, 0)).x,
265        tex2D(shadowMap, shadowUV.xy + float2(+pixeloffset, 0)).x,
266        tex2D(shadowMap, shadowUV.xy + float2(0, -pixeloffset)).x,
267        tex2D(shadowMap, shadowUV.xy + float2(0, +pixeloffset)).x);
268
269        float2 differences = abs( depths.yw - depths.xz );
270        float gradient = min(gradientClamp, max(differences.x, differences.y));
271        float gradientFactor = gradient * gradientScaleBias;
272
273        // visibility function
274        float depthAdjust = gradientFactor + (fixedDepthBias * centerdepth);
275        float finalCenterDepth = centerdepth + depthAdjust;
276
277        // shadowUV.z contains lightspace position of current object
278
279#if FUZZY_TEST
280        // fuzzy test - introduces some ghosting in result and doesn't appear to be needed?
281        //float visibility = saturate(1 + delta_z / (gradient * shadowFuzzyWidth));
282        float visibility = saturate(1 + (finalCenterDepth - shadowUV.z) * shadowFuzzyWidth * shadowUV.w);
283
284        result = vertexColour * visibility;
285#else
286        // hard test
287#if PCF
288        // use depths from prev, calculate diff
289        depths += depthAdjust.xxxx;
290        float final = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
291        final += (depths.x > shadowUV.z) ? 1.0f : 0.0f;
292        final += (depths.y > shadowUV.z) ? 1.0f : 0.0f;
293        final += (depths.z > shadowUV.z) ? 1.0f : 0.0f;
294        final += (depths.w > shadowUV.z) ? 1.0f : 0.0f;
295       
296        final *= 0.2f;
297
298        result = float4(vertexColour.xyz * final, 1);
299       
300#else
301        result = (finalCenterDepth > shadowUV.z) ? vertexColour : float4(0,0,0,1);
302#endif
303
304#endif
305
306
307       
308}
309
Note: See TracBrowser for help on using the repository browser.