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

Revision 3367, 23.7 KB checked in by mattausch, 15 years ago (diff)

working nicely but still artifacts where high convergence regions come on low convergence ones

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