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

Revision 3365, 10.6 KB checked in by mattausch, 15 years ago (diff)

completely changing concept: storing world space position for one lookup!!

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#if 0
42        // hack: prevent to shade the sky
43        if (color.w > DEPTH_THRESHOLD)
44        {
45                outColor = color;
46        }
47        else
48        {
49                if (useAO > .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 = -oldEyePos + worldPos.xyz + difVec;
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 = 4.0f;
296        const float pixelCouldBeValid = 100.0f;
297        // this pixel information has to be discarded in order to not create artifacts
298        const float pixelIsNotValid = 100.0f;
299
300
301        // check if the pixel was outside of the frame buffer
302        if ((oldTexCoords.x <= .0f) || (oldTexCoords.x >= 1.0f) ||
303                (oldTexCoords.y <= .0f) || (oldTexCoords.y >= 1.0f)
304                )
305        {
306                isPixelValid = pixelIsNotValid;
307        }
308        else if (// check if changed from dynamic to not dynamic object
309                 (
310                         // (oldDynamic && !newDynamic) || (!oldDynamic && newDynamic) ||
311                         (
312                          (oldEyeSpaceDepth < DEPTH_THRESHOLD) && (projectedEyeSpaceDepth < DEPTH_THRESHOLD) &&
313                          //(oldDynamic || newDynamic) &&  // check if we have a dynamic object
314                          (depthDif > 5e-2f)))//MIN_DEPTH_DIFF)))
315                          ) // and there is a depth discontinuity
316        {       
317                isPixelValid = pixelCouldBeValid;
318        }
319        else
320        {
321                isPixelValid = pixelIsValid;
322        }
323       
324        //isPixelValid = depthDif;
325
326        return float2(isPixelValid, abs(oldEyeSpaceDepth - projectedEyeSpaceDepth));
327}
328
329
330/** This function is called during downsampling of the buffers for ssao.
331*/
332pixel PrepareSsao(fragment IN,
333                                  uniform sampler2D colorsTex,
334                                  uniform sampler2D normalsTex,
335                                  uniform sampler2D diffVals,
336                                  uniform sampler2D oldTex,
337                                  uniform float4x4 modelViewProj,
338                                  uniform float4x4 oldModelViewProj,
339                                  uniform float3 oldbl,
340                                  uniform float3 oldbr,
341                                  uniform float3 oldtl,
342                                  uniform float3 oldtr,
343                                  uniform float3 oldEyePos,
344                                  uniform sampler2D myTex
345                                  )
346{   
347        pixel pix;
348
349        float4 color = tex2Dlod(colorsTex, float4(IN.texCoord, .0f, .0f));
350        // store scaled view vector so wie don't have to normalize for e.g., SSAO
351        color.w /= length(IN.view);
352
353        const float4 difVec = tex2Dlod(diffVals, float4(IN.texCoord, .0f, .0f));
354        // normalize normal once more because of bilinear interpolation
355        const float3 normal = normalize(tex2Dlod(normalsTex, float4(IN.texCoord, 0, 0)).xyz);
356
357#ifdef PERFORMANCE_TEST
358        // do reprojection and filter out the pixels that are not save
359        const float2 pValid = PixelValid(oldTex,
360                                             color,
361                                                                         difVec.xyz,
362                                                                         IN.texCoord,
363                                                                         IN.view,
364                                                                         oldEyePos,
365                                                                         modelViewProj,                                                   
366                                                                         oldModelViewProj,
367                                                                         oldbl, oldbr, oldtl, oldtr,
368                                                                         myTex
369                                                                         );
370#else
371        const float2 pValid = float2(0, 0);
372#endif
373
374        pix.color = color;
375        pix.color.xy = pValid.xy;
376        pix.color.z = color.w;
377
378        pix.normal = normal;
379
380        return pix;
381}
382
383
384float4 DownSample(fragment IN,
385                                  uniform sampler2D colors,
386                                  uniform float2 downSampleOffs[NUM_DOWNSAMPLES]): COLOR
387{   
388        // let bilinear filtering do its work
389        float4 color = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
390        return color;
391}
Note: See TracBrowser for help on using the repository browser.