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

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