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

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