source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg @ 3351

Revision 3351, 10.4 KB checked in by mattausch, 15 years ago (diff)
Line 
1#include "../shaderenv.h"
2#include "common.h"
3
4struct fragment
5{
6         // normalized screen position
7        float4 pos: WPOS;
8        float2 texCoord: TEXCOORD0;
9        float3 view: TEXCOORD1;
10};
11
12
13struct pixel
14{
15        float4 color: COLOR0;
16        float3 normal: COLOR1;
17        //float3 diffVal: COLOR2;
18};
19
20
21/** function for standard deferred shading
22*/
23float4 shade(fragment IN,
24                         uniform float4 color,
25                         uniform float3 normal,
26                         float3 lightDir,
27                         float4 ao)
28{
29        // diffuse intensity
30        const float angle = saturate(dot(normal, lightDir));
31       
32        float4 lightDiffuse = glstate.light[0].diffuse;
33        float4 diffuse = angle * lightDiffuse;
34
35        // global ambient
36        const float4 ambient = glstate.light[0].ambient;
37       
38        float4 outColor;
39
40        // hack: prevent to shade the sky
41        if (color.w > DEPTH_THRESHOLD)
42        {
43                outColor = color;
44        }
45        else
46        {
47                outColor = (ambient * ao + diffuse) * color;
48                //outColor = ambient + diffuse * color;
49        }
50
51        return outColor;
52}
53
54
55
56/** The mrt shader for standard rendering
57*/
58pixel main(fragment IN,
59                   uniform sampler2D colors,
60                   uniform sampler2D normals,
61                   uniform float3 lightDir,
62                   uniform sampler2D aoTex
63                   )
64{
65        pixel OUT;
66
67        float4 norm = tex2D(normals, IN.texCoord);
68        float4 color = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
69        float4 ao = tex2Dlod(aoTex, float4(IN.texCoord, 0, 0));
70       
71        float3 normal = normalize(norm.xyz);
72        float4 col = shade(IN, color, normal, lightDir, ao);
73       
74        OUT.color = col;
75        // store scaled view vector so wie don't have to normalize for later
76        //OUT.color.w = color.w / length(IN.view);
77        OUT.color.w = color.w;
78
79        return OUT;
80}
81
82
83float CalcShadowTerm(fragment IN,
84                                         uniform sampler2D shadowMap,
85                                         uniform float scale,
86                                         uniform float2 lightSpacePos,
87                                         uniform float depth,
88                                         uniform float2 samples[NUM_PCF_TABS],
89                                         uniform float weights[NUM_PCF_TABS],
90                                         uniform sampler2D noiseTexture
91                                         )
92{
93        //float shadowDepth = tex2D(shadowMap, lightSpacePos).x;
94        //return step(depth, shadowDepth);
95
96        float total_d = .0f;
97        float total_w = .0f;
98
99        for (int i = 0; i < NUM_PCF_TABS; ++ i)
100        {
101                float2 offset;
102                const float w = weights[i];
103
104#if 1
105                ////////////////////
106                //-- add random noise: reflect around random normal vector (warning: slow!)
107
108                float2 mynoise = tex2D(noiseTexture, IN.texCoord * 4.0f).xy;
109                //offset = myreflect(samples[i], mynoise);
110                offset = myrotate(samples[i], mynoise.x);
111#else
112                offset = samples[i];
113#endif
114                // weight with projected coordinate to reach similar kernel size for near and far
115                float2 texcoord = lightSpacePos + offset * scale;
116
117                float shadowDepth = tex2D(shadowMap, texcoord).x;
118
119                total_d += w * step(depth, shadowDepth);
120                total_w += w;
121        }
122
123        total_d /= (float)total_w;
124
125        return total_d;
126}
127
128
129pixel main_shadow(fragment IN,
130                                  uniform sampler2D colors,
131                                  uniform sampler2D positions,
132                                  uniform sampler2D normals,               
133                                  uniform sampler2D shadowMap,
134                                  uniform float4x4 shadowMatrix,
135                                  uniform float sampleWidth,
136                                  uniform sampler2D noiseTex,
137                                  uniform float2 samples[NUM_PCF_TABS],
138                                  uniform float weights[NUM_PCF_TABS],
139                                  uniform float3 lightDir,
140                                  uniform float3 eyePos,
141                                  uniform float3 bl,
142                                  uniform float3 br,
143                                  uniform float3 tl,
144                                  uniform float3 tr
145                                  )
146{
147        pixel OUT;
148
149        const float3 normal = tex2D(normals, IN.texCoord.xy);
150        float4 color = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
151
152        /// reconstruct position from the eye space depth
153        float3 viewDir = IN.view;
154        const float lenView = length(viewDir);
155        viewDir /= lenView;
156
157        const float eyeDepth = tex2Dlod(colors, float4(IN.texCoord, 0, 0)).w;
158        const float4 worldPos = float4(eyePos - viewDir * eyeDepth, 1);
159       
160        // diffuse intensity
161        const float angle = saturate(dot(normal, lightDir));
162        const float4 lightDiffuse = glstate.light[0].diffuse;
163       
164        float4 diffuse = lightDiffuse * angle;
165
166        // hack: prevent shadowing the sky     
167        const bool useShading = (color.w < 1e19f);
168
169        // calc diffuse illumination + shadow term
170        if (useShading &&
171                (angle > 1e-3f) // shadow only if diffuse color has some minimum intensity
172                )
173        {
174                float4 lightSpacePos = mul(shadowMatrix, worldPos);
175                lightSpacePos /= lightSpacePos.w;
176
177                float shadowTerm = CalcShadowTerm(IN, shadowMap, sampleWidth,
178                                                      lightSpacePos.xy, lightSpacePos.z, samples,
179                                                                                  weights, noiseTex);
180                diffuse *= shadowTerm;
181        }
182
183        // light ambient term
184        const float4 ambient = glstate.light[0].ambient;
185        // compute shading
186        OUT.color = useShading ? (ambient + diffuse) * color : color;
187        // store scaled view vector from now on so wie don't have to normalize later (e.g., for ssao)
188        //OUT.color.w = color.w / lenView;
189        OUT.color.w = color.w;
190
191        return OUT;
192}
193
194
195float4 Output(fragment IN, uniform sampler2D colors): COLOR
196{   
197        return tex2Dlod(colors, float4(IN.texCoord, 0, 0));
198}
199
200
201float4 ScaleDepth(fragment IN,
202                                  uniform sampler2D colors): COLOR
203{   
204        float4 color = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
205        // store scaled view vector so wie don't have to normalize for e.g., ssao
206        color.w /= length(IN.view);
207       
208        return color;
209}
210
211
212/** This shader computes the reprojection and checks
213        if the reprojected pixel from last frame is still
214        valid in the current frame
215        */
216inline float2 PixelValid(sampler2D oldTex,
217                                                 float4 color,
218                                                 float3 difVec,
219                                                 float2 texCoord,
220                                                 float3 viewDir,
221                                                 float3 oldEyePos,
222                                                 float4x4 modelViewProj,
223                                                 float4x4 oldModelViewProj,
224                                                 float3 oldbl,
225                                                 float3 oldbr,
226                                                 float3 oldtl,
227                                                 float3 oldtr,
228                                                 sampler2D myTex
229                                                 )
230{
231        // reconstruct position from the eye space depth
232        const float eyeSpaceDepth = color.w;
233        const float4 worldPos = float4(-viewDir * eyeSpaceDepth, 1.0f);
234
235
236        ////////////////
237        //-- calculcate the current projected posiion (also used for next frame)
238       
239        float4 projPos = mul(modelViewProj, worldPos);
240        const float invw = 1.0f / projPos.w;
241        projPos *= invw;
242
243        // compute position from old frame for dynamic objects + translational portion
244        //const float3 translatedPos = difVec - oldEyePos + worldPos.xyz;
245        // don't use difVec here: want to detect if the actual pixel has changed => ssao changed
246        const float3 translatedPos = -oldEyePos + worldPos.xyz;
247
248
249        /////////////////
250        //-- reproject into old frame and calculate texture position of sample in old frame
251
252        // note: the old model view matrix only holds the view orientation part
253        float4 backProjPos = mul(oldModelViewProj, float4(translatedPos, 1.0f));
254        backProjPos /= backProjPos.w;
255       
256        // fit from unit cube into 0 .. 1
257        const float2 oldTexCoords = backProjPos.xy * .5f + .5f;
258       
259        // retrieve the sample from the last frame
260        const float4 oldPixel = tex2Dlod(oldTex, float4(oldTexCoords, .0f, .0f));
261        const float oldDiff = tex2Dlod(myTex, float4(oldTexCoords, .0f, .0f)).x;
262
263        // calculate eye space position of sample in old frame
264        const float oldEyeSpaceDepth = oldPixel.w;
265
266        // vector from eye pos to old sample
267        const float3 oldViewDir = Interpol(oldTexCoords, oldbl, oldbr, oldtl, oldtr);
268        const float invLen = 1.0f / length(oldViewDir);
269        const float projectedEyeSpaceDepth = invLen * length(translatedPos);
270       
271        const float depthDif = abs(1.0f - oldEyeSpaceDepth / projectedEyeSpaceDepth);
272        const float squaredLen = SqrLen(difVec);
273       
274
275        // test if this pixel was valid in the old frame
276        float isPixelValid;
277
278        // check if the pixel belonged to a dynamic object in the last frame
279        const bool newDynamic = (squaredLen > DYNAMIC_OBJECTS_THRESHOLD);
280        const bool oldDynamic = (oldDiff > DYNAMIC_OBJECTS_THRESHOLD);
281
282
283        // actually 0 means pixel is valid
284        const float pixelIsValid = .0f;
285        // means that we only use slight temporal coherence over some frames
286        // so that there is no noticeable drag
287        const float pixelCouldBeValid = 2.0f;
288        // this pixel information has to be discarded in order to not create artifacts
289        const float pixelIsNotValid = 100.0f;
290
291
292        // check if the pixel was outside of the frame buffer
293        if ((oldTexCoords.x <= .0f) || (oldTexCoords.x >= 1.0f) ||
294                (oldTexCoords.y <= .0f) || (oldTexCoords.y >= 1.0f)
295                )
296        {
297                isPixelValid = pixelIsNotValid;
298        }
299        else if ( // check if changed from dynamic to not dynamic object
300                 ((oldDynamic && !newDynamic) || (!oldDynamic && newDynamic) ||
301                         (
302                          (oldEyeSpaceDepth < DEPTH_THRESHOLD) && (projectedEyeSpaceDepth < DEPTH_THRESHOLD) &&
303                          (oldDynamic || newDynamic) &&  // check if we have a dynamic object
304                          (depthDif > MIN_DEPTH_DIFF)))) // and there is a depth discontinuity
305        {       
306                isPixelValid = pixelCouldBeValid;
307        }
308        else
309        {
310                isPixelValid = pixelIsValid;
311        }
312       
313        return float2(isPixelValid, abs(oldEyeSpaceDepth - projectedEyeSpaceDepth));
314}
315
316
317/** This function is called during downsampling of the buffers
318        for ssao.
319*/
320pixel PrepareSsao(fragment IN,
321                                  uniform sampler2D colorsTex,
322                                  uniform sampler2D normalsTex,
323                                  uniform sampler2D diffVals,
324                                  uniform sampler2D oldTex,
325                                  uniform float4x4 modelViewProj,
326                                  uniform float4x4 oldModelViewProj,
327                                  uniform float3 oldbl,
328                                  uniform float3 oldbr,
329                                  uniform float3 oldtl,
330                                  uniform float3 oldtr,
331                                  uniform float3 oldEyePos,
332                                  uniform sampler2D myTex
333                                  )
334{   
335        pixel pix;
336
337        float4 color = tex2Dlod(colorsTex, float4(IN.texCoord, .0f, .0f));
338        // store scaled view vector so wie don't have to normalize for e.g., SSAO
339        color.w /= length(IN.view);
340
341        const float4 difVec = tex2Dlod(diffVals, float4(IN.texCoord, 0, 0));
342        // normalize normal once more because of bilinear interpolation
343        const float3 normal = normalize(tex2Dlod(normalsTex, float4(IN.texCoord, 0, 0)).xyz);
344
345#ifdef PERFORMANCE_TEST
346        // do reprojection and filter out the pixels that are not save
347        const float2 pValid = PixelValid(oldTex,
348                                             color,
349                                                                         difVec.xyz,
350                                                                         IN.texCoord,
351                                                                         IN.view,
352                                                                         oldEyePos,
353                                                                         modelViewProj,                                                   
354                                                                         oldModelViewProj,
355                                                                         oldbl, oldbr, oldtl, oldtr,
356                                                                         myTex
357                                                                         );
358#else
359        const float2 pValid = float2(0,0);
360#endif
361
362        pix.color = color;
363        pix.color.xy = pValid.xy;
364        pix.color.z = color.w;
365
366        pix.normal = normal;
367
368        return pix;
369}
370
371
372float4 DownSample(fragment IN,
373                                  uniform sampler2D colors,
374                                  uniform float2 downSampleOffs[NUM_DOWNSAMPLES]): COLOR
375{   
376        // let bilinear filtering do its work
377        float4 color = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
378        return color;
379}
Note: See TracBrowser for help on using the repository browser.