source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg @ 3372

Revision 3372, 22.8 KB checked in by mattausch, 15 years ago (diff)

reverted but now a good version

Line 
1#include "../shaderenv.h"
2#include "common.h"
3
4////////////////////
5// Screen Spaced Ambient Occlusion shader
6// based on shader of Alexander Kusternig
7
8
9#define USE_EYESPACE_DEPTH 1
10
11
12struct fragment
13{
14        float2 texCoord: TEXCOORD0;
15        float3 view: TEXCOORD1;
16};
17
18
19struct pixel2
20{
21        float4 illum_col: COLOR0;
22};
23
24
25// this function is inspired from the paper of shamulgaan in order
26// to get a physical expression for the occlusion culling
27inline float occlusionPower(float radius, float dist)
28{
29        return 6.283185307179586476925286766559f * (1.0f - cos(asin(radius / dist)));
30}
31
32
33
34// reconstruct world space position
35inline float3 ReconstructSamplePos(float eyeSpaceDepth,
36                                                                   float2 texcoord,
37                                                                   float3 bl, float3 br, float3 tl, float3 tr)
38{
39        float3 viewVec = Interpol(texcoord, bl, br, tl, tr);
40        float3 samplePos = -viewVec * eyeSpaceDepth;
41
42        return samplePos;
43}
44
45
46float ComputeConvergence(uniform sampler2D tex, float2 texCoord, float2 res)
47{
48        // get the minimum convergence by exactly sampling the 4 surrounding
49        // texels in the old texture, otherwise flickering because convergence
50        // will be interpolated when upsampling and filter size does not match!
51
52        const float2 invRes = float2(1.0f / res.x, 1.0f / res.y);
53
54        // get position exactly between texel centers
55        float2 center = (floor(texCoord * res) + float2(.5f)) * invRes;
56       
57        //const float convergence = tex2Dlod(tex, float4(center, 0, 0)).y;
58        const float convergence = tex2Dlod(tex, float4(texCoord, 0, 0)).y;
59
60        return convergence;
61}
62
63/** This shader computes the reprojection and stores
64        the ssao value of the old pixel as well as the
65        weight of the pixel in the new frame.
66*/
67inline float3 Reproject(float4 worldPos,
68                                                float eyeSpaceDepth,
69                                                float2 texcoord0,
70                                                float3 oldEyePos,
71                                                sampler2D oldTex,
72                                                float4x4 oldModelViewProj,
73                                                sampler2D colors,
74                                                float3 projPos,
75                                                float invW,
76                                                float3 oldbl,
77                                                float3 oldbr,
78                                                float3 oldtl,
79                                                float3 oldtr,
80                                                float3 diffVec
81                                                )
82{
83        // compute position from old frame for dynamic objects + translational portion
84        const float3 translatedPos = diffVec - oldEyePos + worldPos.xyz;
85
86
87        /////////////////
88        //-- reproject into old frame and calculate texture position of sample in old frame
89
90        // note: the old model view matrix only holds the view orientation part
91        float4 backProjPos = mul(oldModelViewProj, float4(translatedPos, 1.0f));
92        backProjPos /= backProjPos.w;
93       
94        // fit from unit cube into 0 .. 1
95        const float2 oldTexCoords = backProjPos.xy * 0.5f + 0.5f;
96        // retrieve the sample from the last frame
97        const float4 oldPixel = tex2Dlod(oldTex, float4(oldTexCoords, .0f, .0f));
98
99        // the ssao value in the old frame
100        const float ssao = oldPixel.x;
101
102        // calculate eye space position of sample in old frame
103        const float oldEyeSpaceDepth = oldPixel.w;
104
105        // vector from eye pos to old sample
106        const float3 viewVec = Interpol(oldTexCoords, oldbl, oldbr, oldtl, oldtr);
107        const float invLen = 1.0f / length(viewVec);
108        const float projectedEyeSpaceDepth = invLen * length(translatedPos);
109        //const float projectedEyeSpaceDepth = length(translatedPos);
110       
111        const float depthDif = abs(1.0f - oldEyeSpaceDepth / projectedEyeSpaceDepth);
112
113        // the weight of the accumulated samples from the previous frames
114        float w;
115        float idx;
116
117
118        //////////////
119        //-- reuse old value only if it was still valid in the old frame
120
121        if (1
122                && (oldTexCoords.x > .0f) && (oldTexCoords.x < 1.0f)
123                && (oldTexCoords.y > .0f) && (oldTexCoords.y < 1.0f)
124                && (depthDif <= MIN_DEPTH_DIFF)
125                )
126        {
127#if 0
128                idx = floor(oldPixel.z);
129#else
130
131                // nearest neighbour
132                float2 center;
133                center.x = (floor(oldTexCoords.x * 1024) + .5f) / 1024;
134                center.y = (floor(oldTexCoords.y * 768) + .5f) / 768;
135               
136                const float4 oldPixelExact = tex2Dlod(oldTex, float4(center, .0f, .0f));
137                idx = oldPixelExact.z;
138#endif
139
140                w = oldPixel.y;
141        }
142        else
143        {       
144                w   = .0f;
145                idx = .0f;
146        }
147
148        return float3(ssao, w, idx);
149}
150
151
152/** The ssao shader returning the an intensity value between 0 and 1.
153        This version of the ssao shader uses the dotproduct between
154        pixel-to-sample direction and sample normal as weight.
155
156    The algorithm works like the following:
157        1) Check in a circular area around the current position.
158        2) Shoot vectors to the positions there, and check the angle to these positions.
159        3) Summing up these angles gives an estimation of the occlusion at the current position.
160*/
161float3 ssao2(fragment IN,
162                         sampler2D colors,
163                         sampler2D noiseTex,
164                         sampler2D samples,
165                         float3 normal,
166                         float3 centerPosition,
167                         float radius,
168                         float3 bl,
169                         float3 br,
170                         float3 tl,
171                         float3 tr,
172                         float3 viewDir,
173                         float convergence,
174                         float sampleIntensity,
175                         bool isMovingObject,
176                         sampler2D normalTex,
177                         float idx
178                         )
179{
180        float total_ao = .0f;
181        float validSamples = .0f;
182        float numSamples = .0f;
183
184        for (int i = 0; i < NUM_SAMPLES; ++ i)
185        {
186                float2 offset;
187
188                const float2 ssaoOffset =
189                        tex2Dlod(samples, float4((0.5f + i + idx) / NUM_PRECOMPUTED_SAMPLES, 0.5f, .0f, .0f)).xy;
190
191                ////////////////////
192                //-- add random noise: reflect around random normal vector
193                //-- (affects performance for some reason!)
194
195                if (!USE_OPTIMIZATION ||
196                        (convergence < SSAO_CONVERGENCE_THRESHOLD))
197                {
198                        float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
199                        //offset = myreflect(samples[i], mynoise);
200                        //offset = myrotate(samples[i], mynoise.x);
201                        offset = myrotate(ssaoOffset, mynoise.x);
202                }
203                else
204                {
205                        offset = ssaoOffset;
206                }
207               
208                // weight with projected coordinate to reach similar kernel size for near and far
209                const float2 texcoord = IN.texCoord.xy + offset * radius;
210
211                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
212                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
213               
214
215                ////////////////
216                //-- compute contribution of sample using the direction and angle
217
218                float3 dirSample = samplePos - centerPosition;
219
220                const float minDist = 1e-6f;
221                const float delta = 1e-3f;
222
223                const float lengthToSample = length(dirSample);
224                const float sampleWeight = 1.0f / (lengthToSample + delta);
225
226                dirSample /= max(lengthToSample, minDist); // normalize
227
228
229                // angle between current normal and direction to sample controls AO intensity.
230                const float cosAngle = dot(dirSample, normal);
231
232                // the normal of the current sample
233                const float3 sampleNormal = normalize(tex2Dlod(normalTex, float4(texcoord, 0, 0)).xyz);
234               
235                // angle between current normal and direction to sample controls AO intensity.
236                //const float cosAngle2 = dot(-dirSample, sampleNormal);
237                const float cosAngle2 = .5f + dot(sampleNormal, -normal) * .5f;
238
239                dirSample *= minDist;
240                const float aoContrib = sampleIntensity * sampleWeight;
241
242                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
243                //total_ao += max(cosAngle, .0f) * max(cosAngle2, .0f) * aoContrib;
244                total_ao += max(cosAngle, .0f) * cosAngle2 * aoContrib;
245
246                ++ numSamples;
247
248                // check if the samples have been valid in the last frame
249                // only mark sample as invalid if in the last / current frame
250                // they possibly have any influence on the ao
251
252                const float changeFactor = sampleColor.y;
253                const float pixelValid = sampleColor.x;
254
255                // hack:
256                // we check if the sample could have been near enough
257                // to the current pixel or if the angle is small enough
258                // to have any influence in the current or last frame
259#if 1
260                const float tooFarAway = step(0.5f, lengthToSample - changeFactor);
261                const float partlyResetThres = 1.0f;
262
263                if (pixelValid <= partlyResetThres)
264                        validSamples = max(validSamples, pixelValid * (1.0f - tooFarAway) * step(-0.1f, cosAngle));
265                else
266                        validSamples = max(validSamples, pixelValid);
267#endif
268
269#ifdef USE_GTX
270                // we can bail out early and use a minimal #samples)
271                // if some conditions are met as long as the hardware supports it
272                if (numSamples >= MIN_SAMPLES)
273                {
274                        //break;
275                        // if the pixel belongs to a static object and all the samples stay valid in the current frame
276                        if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break;
277                        // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high
278                        // (=> there was no discontinuity recently)
279                        //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break;
280                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
281                }
282#endif
283        }
284
285        // "normalize" ao contribution
286        total_ao /= numSamples;
287
288#if 1
289        // if surface normal perpenticular to view dir, approx. half of the samples will not count
290        // => compensate for this (on the other hand, projected sampling area could be larger!)
291        const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f);
292        total_ao *= viewCorrection;
293#endif
294
295        //return float3(total_ao, validSamples, numSamples);
296        return float3(min(1.0f, total_ao), validSamples, numSamples);
297}
298
299//#define TRYOUT
300
301#ifdef TRYOUT
302
303/** The ssao shader returning the an intensity value between 0 and 1.
304        This version of the ssao shader uses the dotproduct between
305        pixel-to-sample direction and sample normal as weight.
306
307    The algorithm works like the following:
308        1) Check in a circular area around the current position.
309        2) Shoot vectors to the positions there, and check the angle to these positions.
310        3) Summing up these angles gives an estimation of the occlusion at the current position.
311*/
312float3 ssao(fragment IN,
313                        sampler2D colors,
314                        sampler2D noiseTex,
315                        sampler2D samples,
316                        float3 normal,
317                        float3 centerPosition,
318                        float radius,
319                        float3 bl,
320                        float3 br,
321                        float3 tl,
322                        float3 tr,
323                        float3 viewDir,
324                        float convergence,
325                        float sampleIntensity,
326                        bool isMovingObject,
327                        float oldIdx
328                        )
329{
330        float total_ao = .0f;
331        float validSamples = .0f;
332        float numSamples = .0f;
333
334        for (int i = 0; i < NUM_SAMPLES; ++ i)
335        {
336                float2 offset;
337
338                const float2 ssaoOffset =
339                        tex2Dlod(samples, float4((0.5f + i + oldIdx) / NUM_PRECOMPUTED_SAMPLES, 0.5f, .0f, .0f)).xy;
340
341
342                ////////////////////
343                //-- add random noise: reflect around random normal vector
344                //-- (affects performance for some reason!)
345
346                if (!USE_OPTIMIZATION ||
347                        (convergence < SSAO_CONVERGENCE_THRESHOLD))
348                {
349                        float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
350                        //offset = myrotate(samples[i], mynoise.x);
351                        offset = myrotate(ssaoOffset, mynoise.x);
352                }
353                else
354                {
355                        offset = ssaoOffset;
356                }
357
358
359                // weight with projected coordinate to reach similar kernel size for near and far
360                const float2 texcoord = IN.texCoord.xy + offset * radius;
361
362                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
363                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
364               
365
366                ////////////////
367                //-- compute contribution of sample using the direction and angle
368
369                float3 dirSample = samplePos - centerPosition;
370
371                const float minDist = 1e-6f;
372                const float eps = 1e-3f;
373
374                const float lengthToSample = length(dirSample);
375                const float sampleWeight = 1.0f / max(lengthToSample, eps);
376
377                dirSample /= max(length(dirSample), minDist); // normalize
378
379                // angle between current normal and direction to sample controls AO intensity.
380                const float cosAngle = dot(dirSample, normal);
381
382                //const float aoContrib = sampleIntensity / sqrLen;
383                const float aoContrib = sampleIntensity * sampleWeight;
384                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
385
386                total_ao += max(cosAngle, .0f) * aoContrib;
387
388                ++ numSamples;
389
390#ifdef PERFORMANCE_TEST
391                // check if the samples have been valid in the last frame
392                // only mark sample as invalid if in the last / current frame
393                // they possibly have any influence on the AO
394
395                const float changeFactor = sampleColor.y;
396                const float pixelValid = sampleColor.x;
397
398                // hack:
399                // we check if the sample could have been near enough to the current pixel
400                // or if the angle is small enough
401                // to have any influence in the current or last frame
402
403#if 1
404                const float partlyResetThres = 1.0f;
405
406                const float tooFarAway = step(.5f, lengthToSample - changeFactor);
407                if (0)//pixelValid <= partlyResetThres)
408                        validSamples = max(validSamples, pixelValid * (1.0f - tooFarAway) * step(-.1f, cosAngle));
409                else
410                        validSamples = max(validSamples, pixelValid);
411#endif
412
413#ifdef USE_GTX
414                // we can bail out early and use a minimal #samples)
415                // if some conditions are met as long as the hardware supports it
416                if (numSamples >= MIN_SAMPLES)
417                {
418                        //break;
419                        // if the pixel belongs to a static object and all the samples stay valid in the current frame
420                        if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break;
421                        // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high
422                        // (=> there was no discontinuity recently)
423                        //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break;
424                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
425                }
426#endif
427
428#endif // PERFORMANCE_TEST
429        }
430
431        // "normalize" ao contribution
432        total_ao /= numSamples;
433
434#if 1
435        // if surface normal perpenticular to view dir, approx. half of the samples will not count
436        // => compensate for this (on the other hand, projected sampling area could be larger!)
437        const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f);
438        total_ao *= viewCorrection;
439#endif
440
441        //return float3(total_ao, validSamples, numSamples);
442        return float3(min(1.0f, total_ao), validSamples, numSamples);
443}
444
445#else
446
447float3 ssao(fragment IN,
448                        sampler2D colors,
449                        sampler2D noiseTex,
450                        float2 dummySamples[NUM_SAMPLES],
451                        sampler2D samples,
452                        float3 normal,
453                        float3 centerPosition,
454                        float radius,
455                        float3 bl,
456                        float3 br,
457                        float3 tl,
458                        float3 tr,
459                        float3 viewDir,
460                        float convergence,
461                        float sampleIntensity,
462                        bool isMovingObject,
463                        float oldIdx,
464                        sampler2D attribsTex,
465                        float3 oldPos
466                        )
467{
468        float total_ao = .0f;
469        float validSamples = .0f;
470        float numSamples = .0f;
471
472        //float3 diffVec = tex2Dlod(attribsTex, float4(IN.texCoord, 0, 0)).xyz;
473
474        for (int i = 0; i < NUM_SAMPLES; ++ i)
475        {
476                float2 offset;
477
478                const float2 ssaoOffset = tex2Dlod(samples, float4((.5f + i + floor(oldIdx)) / NUM_PRECOMPUTED_SAMPLES, .5f, .0f, .0f)).xy;
479                //const float2 ssaoOffset = dummySamples[i];
480
481                ////////////////////
482                //-- add random noise: reflect around random normal vector
483                //-- (affects performance for some reason!)
484
485                if (!USE_OPTIMIZATION ||
486                        (convergence < SSAO_CONVERGENCE_THRESHOLD))
487                {
488                        float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
489                        //offset = myreflect(samples[i], mynoise); offset = myrotate(samples[i], mynoise.x);
490                        offset = myrotate(ssaoOffset, mynoise.x);
491                }
492                else
493                {
494                        offset = ssaoOffset;
495                }
496
497
498                // weight with projected coordinate to reach similar kernel size for near and far
499                const float2 texcoord = IN.texCoord.xy + offset * radius;
500
501                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
502                const float3 oldSamplePos = sampleColor.xyz;
503                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
504               
505               
506
507                ////////////////
508                //-- compute contribution of sample using the direction and angle
509
510                float3 dirSample = samplePos - centerPosition;
511
512                const float eps = 1e-3f;
513
514                const float lengthToSample = length(dirSample);
515                const float sampleWeight = 1.0f / max(lengthToSample, eps);
516
517                dirSample /= max(length(dirSample), eps); // normalize
518
519                // angle between current normal and direction to sample controls AO intensity.
520                const float cosAngle = dot(dirSample, normal);
521
522                //const float aoContrib = sampleIntensity / sqrLen;
523                const float aoContrib = sampleIntensity * sampleWeight;
524                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
525
526                total_ao += max(cosAngle, .0f) * aoContrib;
527                ++ numSamples;
528
529
530#ifdef PERFORMANCE_TEST
531                // check if the samples have been valid in the last frame
532                // only mark sample as invalid if in the last / current frame
533                // they possibly have any influence on the ao
534
535                const float3 oldVector = oldSamplePos - oldPos;
536                const float oldDistance = length(oldVector);
537                //const float cosAngle2 = dot(oldVector, normal);
538               
539                const float distanceDiff = abs(oldDistance - lengthToSample);
540
541                float pixelValid = .0f;
542
543                if ((texcoord.x > .0f) && (texcoord.x < 1.0f) && (texcoord.y > .0f) && (texcoord.y < 1.0f))
544                {
545                        if ((oldSamplePos.x > 1e14f))// || ((cosAngle >= 0) && (distanceDiff > 1e-3f)))
546                        {
547                                pixelValid = 100.0f;
548                        }
549                        else if ((cosAngle >= 0) && (distanceDiff > 1e-3f))
550                        {
551                                pixelValid = 5.0f;
552                        }
553                }
554
555                validSamples = max(validSamples, pixelValid);
556
557#ifdef USE_GTX
558                // we can bail out early and use a minimal #samples)
559                // if some conditions are met as long as the hardware supports it
560                if (numSamples >= MIN_SAMPLES)
561                {
562                        //break;
563                        // if the pixel belongs to a static object and all the samples stay valid in the current frame
564                        if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break;
565                        // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high
566                        // (=> there was no discontinuity recently)
567                        //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break;
568                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
569                }
570#endif
571
572#endif // PERFORMANCE_TEST
573        }
574
575        // "normalize" ao contribution
576        total_ao /= numSamples;
577
578#if 1
579        // if surface normal perpenticular to view dir, approx. half of the samples will not count
580        // => compensate for this (on the other hand, projected sampling area could be larger!)
581        const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f);
582        total_ao *= viewCorrection;
583#endif
584
585        //return float3(total_ao, validSamples, numSamples);
586        return float3(min(1.0f, total_ao), validSamples, numSamples);
587}
588#endif
589
590
591/** The mrt shader for screen space ambient occlusion
592*/
593pixel2 main(fragment IN,
594                        uniform sampler2D colors,
595                        uniform sampler2D normals,
596                        uniform sampler2D noiseTex,
597                        uniform sampler2D samples,
598                        uniform float2 dummySamples[NUM_SAMPLES],
599                        uniform sampler2D oldTex,
600                        uniform float4x4 modelViewProj,
601                        uniform float4x4 oldModelViewProj,
602                        uniform float temporalCoherence,
603                        uniform float3 bl,
604                        uniform float3 br,
605                        uniform float3 tl,
606                        uniform float3 tr,
607                        uniform float3 oldEyePos,
608                        uniform float3 oldbl,
609                        uniform float3 oldbr,
610                        uniform float3 oldtl,
611                        uniform float3 oldtr,
612                        uniform sampler2D attribsTex,
613                        uniform float kernelRadius,
614                        uniform float sampleIntensity
615                        ,uniform float dummyIdx
616                        )
617{
618        pixel2 OUT;
619
620        //const float3 normal = normalize(tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz);
621        const float3 normal = tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz;
622
623        // reconstruct position from the eye space depth
624        const float3 viewDir = IN.view;
625        const float4 mycolor = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
626        const float eyeSpaceDepth = mycolor.w;
627        const float4 eyeSpacePos = float4(-viewDir * eyeSpaceDepth, 1.0f);
628
629
630        ////////////////
631        //-- calculcate the current projected posiion (also used for next frame)
632       
633        float4 projPos = mul(modelViewProj, eyeSpacePos);
634        const float invw = 1.0f / projPos.w;
635        projPos *= invw;
636       
637        //const float radiusMult = kernelRadius;
638        //const float radiusMult = 3e-2;
639        const float radiusMult = kernelRadius * invw;
640       
641#ifdef PERFORMANCE_TEST
642
643        float3 diffVec = tex2Dlod(attribsTex, float4(IN.texCoord, 0, 0)).xyz;
644
645        const float sqrMoveSpeed = SqrLen(diffVec);
646        const bool isMovingObject = (sqrMoveSpeed > DYNAMIC_OBJECTS_THRESHOLD);
647
648       
649        /////////////////
650        //-- compute temporal reprojection
651
652        float3 temporalVals = Reproject(eyeSpacePos, eyeSpaceDepth, IN.texCoord, oldEyePos,
653                                        oldTex, oldModelViewProj,
654                                                                        colors,
655                                                                        projPos.xyz,
656                                                                        invw,
657                                                                        oldbl, oldbr, oldtl, oldtr,
658                                                                        diffVec
659                                                                        );
660       
661        const float oldSsao = temporalVals.x;
662       
663        float oldWeight = temporalVals.y;
664        float oldIdx = temporalCoherence > 1 ? temporalVals.z : 0;
665        //float oldIdx = temporalVals.z;
666       
667#else
668
669        const float3 diffVec      = float3(.0f);
670        const bool isMovingObject = false;
671        const float oldSsao       = .0f;
672       
673        float oldWeight = .0f;
674        float oldIdx    = .0f;
675       
676#endif
677
678        float3 ao;
679        //$$temp matt
680        //oldIdx = dummyIdx;
681
682        // cull background note: this should be done with the stencil buffer
683        if (eyeSpaceDepth < DEPTH_THRESHOLD)
684        {
685#ifdef TRYOUT
686                ao = ssao(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz,
687                              radiusMult, bl, br, tl, tr, normalize(viewDir),
688                              oldWeight, sampleIntensity, isMovingObject, oldIdx);
689#else
690
691                ao = ssao(IN, colors, noiseTex, dummySamples, samples,
692                              normal, eyeSpacePos.xyz, radiusMult, bl,
693                              br, tl, tr, normalize(viewDir),
694                              oldWeight, sampleIntensity, isMovingObject, oldIdx,
695                              attribsTex, mycolor.xyz);
696#endif                           
697        }
698        else
699        {
700                 ao = float3(1.0f);
701        }
702
703
704#ifdef PERFORMANCE_TEST
705
706        ///////////
707        //-- check if we have to reset pixel because one of the sample points was invalid
708        //-- only do this if the current pixel does not belong to a moving object
709
710        // the weight equals the number of sampled shot in this pass
711        const float newWeight = ao.z;
712        // completely reset the ao in this pixel
713        const float completelyResetThres = 20.0f;
714        // don't fully reset the ao in this pixel, but give low weight to old solution
715        const float partlyResetThres = 1.0f;
716       
717        // the new index for the next frame
718        float newIdx;
719        // the new weight for the next frame
720        float combinedWeight;
721
722        // don't check for moving objects, otherwise almost no coherence
723        if (ao.y > completelyResetThres)
724        {
725                oldWeight = newIdx = .0f;
726        }
727        else
728        {
729                newIdx = oldIdx + newWeight;
730        }
731
732        if (ao.y > partlyResetThres)
733        {
734                const float factor = 3.0f;
735
736                oldWeight = min(oldWeight, factor * NUM_SAMPLES);
737
738                if (newIdx >= factor * NUM_SAMPLES)
739                {
740                        newIdx = .0f;
741                        //oldWeight = .0f;
742                }
743
744                //combinedWeight = oldWeight;
745        }
746
747        // the new weight for the next frame
748        combinedWeight = clamp(newWeight + oldWeight, .0f, temporalCoherence);
749
750
751        //////////
752        //-- blend ao between old and new samples (and avoid division by zero)
753
754        OUT.illum_col.x = ao.x * newWeight + oldSsao * oldWeight;
755        OUT.illum_col.x /= (newWeight + oldWeight);
756
757        OUT.illum_col.y = combinedWeight;
758        OUT.illum_col.z = newIdx; // the new index
759        OUT.illum_col.w = eyeSpaceDepth;
760
761#else
762
763        OUT.illum_col.x = ao.x;
764        OUT.illum_col.w = eyeSpaceDepth;
765       
766#endif
767
768        return OUT;
769}
Note: See TracBrowser for help on using the repository browser.