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

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

debug 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)) * 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 = myrotate(samples[i], mynoise.x);
362                        offset = myrotate(ssaoOffset, mynoise.x);
363                }
364                else
365                {
366                        offset = ssaoOffset;
367                }
368
369
370                // weight with projected coordinate to reach similar kernel size for near and far
371                const float2 texcoord = IN.texCoord.xy + offset * radius;
372
373                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
374                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
375               
376
377                ////////////////
378                //-- compute contribution of sample using the direction and angle
379
380                float3 dirSample = samplePos - centerPosition;
381
382                const float minDist = 1e-6f;
383                const float eps = 1e-3f;
384
385                const float lengthToSample = length(dirSample);
386                const float sampleWeight = 1.0f / max(lengthToSample, eps);
387
388                dirSample /= max(length(dirSample), minDist); // normalize
389
390                // angle between current normal and direction to sample controls AO intensity.
391                const float cosAngle = dot(dirSample, normal);
392
393                //const float aoContrib = sampleIntensity / sqrLen;
394                const float aoContrib = sampleIntensity * sampleWeight;
395                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
396
397                total_ao += max(cosAngle, .0f) * aoContrib;
398
399                ++ numSamples;
400
401#ifdef PERFORMANCE_TEST
402                // check if the samples have been valid in the last frame
403                // only mark sample as invalid if in the last / current frame
404                // they possibly have any influence on the AO
405
406                const float changeFactor = sampleColor.y;
407                const float pixelValid = sampleColor.x;
408
409                // hack:
410                // we check if the sample could have been near enough to the current pixel
411                // or if the angle is small enough
412                // to have any influence in the current or last frame
413
414#if 1
415                const float partlyResetThres = 1.0f;
416
417                const float tooFarAway = step(.5f, lengthToSample - changeFactor);
418                if (0)//pixelValid <= partlyResetThres)
419                        validSamples = max(validSamples, pixelValid * (1.0f - tooFarAway) * step(-.1f, cosAngle));
420                else
421                        validSamples = max(validSamples, pixelValid);
422#endif
423
424#ifdef USE_GTX
425                // we can bail out early and use a minimal #samples)
426                // if some conditions are met as long as the hardware supports it
427                if (numSamples >= MIN_SAMPLES)
428                {
429                        //break;
430                        // if the pixel belongs to a static object and all the samples stay valid in the current frame
431                        if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break;
432                        // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high
433                        // (=> there was no discontinuity recently)
434                        //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break;
435                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
436                }
437#endif
438
439#endif // PERFORMANCE_TEST
440        }
441
442        // "normalize" ao contribution
443        total_ao /= numSamples;
444
445#if 1
446        // if surface normal perpenticular to view dir, approx. half of the samples will not count
447        // => compensate for this (on the other hand, projected sampling area could be larger!)
448        const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f);
449        total_ao *= viewCorrection;
450#endif
451
452        //return float3(total_ao, validSamples, numSamples);
453        return float3(min(1.0f, total_ao), validSamples, numSamples);
454}
455
456#else
457
458float3 ssao(fragment IN,
459                        sampler2D colors,
460                        sampler2D noiseTex,
461                        float2 dummySamples[NUM_SAMPLES],
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 = tex2Dlod(samples, float4((0.5f + i + oldIdx) / NUM_PRECOMPUTED_SAMPLES, .5f, .0f, .0f)).xy;
490                const float2 ssaoOffset = dummySamples[i];
491
492                ////////////////////
493                //-- add random noise: reflect around random normal vector
494                //-- (affects performance for some reason!)
495
496                if (0)//!USE_OPTIMIZATION ||
497                        //(convergence < SSAO_CONVERGENCE_THRESHOLD))
498                {
499                        float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
500                        //offset = myreflect(samples[i], mynoise); offset = myrotate(samples[i], mynoise.x);
501                        offset = myrotate(ssaoOffset, mynoise.x);
502                }
503                else
504                {
505                        offset = ssaoOffset;
506                }
507
508
509                // weight with projected coordinate to reach similar kernel size for near and far
510                const float2 texcoord = IN.texCoord.xy + offset * radius;
511
512                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
513                const float3 oldSamplePos = sampleColor.xyz;
514                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
515               
516               
517
518                ////////////////
519                //-- compute contribution of sample using the direction and angle
520
521                float3 dirSample = samplePos - centerPosition;
522
523                const float minDist = 1e-6f;
524                const float eps = 1e-3f;
525
526                const float lengthToSample = length(dirSample);
527                const float sampleWeight = 1.0f / max(lengthToSample, eps);
528
529                dirSample /= max(length(dirSample), minDist); // normalize
530
531                // angle between current normal and direction to sample controls AO intensity.
532                const float cosAngle = dot(dirSample, normal);
533
534                //const float aoContrib = sampleIntensity / sqrLen;
535                const float aoContrib = sampleIntensity * sampleWeight;
536                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
537
538                total_ao += max(cosAngle, .0f) * aoContrib;
539                ++ numSamples;
540
541
542//#ifdef PERFORMANCE_TEST
543#if 1
544                // check if the samples have been valid in the last frame
545                // only mark sample as invalid if in the last / current frame
546                // they possibly have any influence on the ao
547
548                const float3 oldVector = oldSamplePos - oldPos;
549                const float oldDistance = length(oldVector);
550                //const float cosAngle2 = dot(oldVector, normal);
551               
552                const float distanceDiff = abs(oldDistance - lengthToSample);
553
554                float pixelValid = (oldSamplePos.x > 1e14f) ? 100.0f : .0f;
555
556                if ((cosAngle >= 0) && (pixelValid < 90.0f))// || (cosAngle2 >= 0))
557                {
558                        pixelValid = (distanceDiff > 1e-3f) ? 100.0f : .0f;
559                        //pixelValid = (distanceDiff > 1e-3f) ? 5.0f : .0f;
560                }
561
562                validSamples = max(validSamples, pixelValid);
563
564#ifdef USE_GTX
565                // we can bail out early and use a minimal #samples)
566                // if some conditions are met as long as the hardware supports it
567                if (numSamples >= MIN_SAMPLES)
568                {
569                        //break;
570                        // if the pixel belongs to a static object and all the samples stay valid in the current frame
571                        if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break;
572                        // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high
573                        // (=> there was no discontinuity recently)
574                        //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break;
575                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
576                }
577#endif
578
579#endif // PERFORMANCE_TEST
580        }
581
582        // "normalize" ao contribution
583        total_ao /= numSamples;
584
585#if 1
586        // if surface normal perpenticular to view dir, approx. half of the samples will not count
587        // => compensate for this (on the other hand, projected sampling area could be larger!)
588        const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f);
589        total_ao *= viewCorrection;
590#endif
591
592        //return float3(total_ao, validSamples, numSamples);
593        return float3(min(1.0f, total_ao), validSamples, numSamples);
594}
595#endif
596
597
598/** The mrt shader for screen space ambient occlusion
599*/
600pixel2 main(fragment IN,
601                        uniform sampler2D colors,
602                        uniform sampler2D normals,
603                        uniform sampler2D noiseTex,
604                        uniform sampler2D samples,
605                        uniform float2 dummySamples[NUM_SAMPLES],
606                        uniform sampler2D oldTex,
607                        uniform float4x4 modelViewProj,
608                        uniform float4x4 oldModelViewProj,
609                        uniform float temporalCoherence,
610                        uniform float3 bl,
611                        uniform float3 br,
612                        uniform float3 tl,
613                        uniform float3 tr,
614                        uniform float3 oldEyePos,
615                        uniform float3 oldbl,
616                        uniform float3 oldbr,
617                        uniform float3 oldtl,
618                        uniform float3 oldtr,
619                        uniform sampler2D attribsTex,
620                        uniform float kernelRadius,
621                        uniform float sampleIntensity
622                        ,uniform float dummyIdx
623                        )
624{
625        pixel2 OUT;
626
627        //const float3 normal = normalize(tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz);
628        const float3 normal = tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz;
629
630        // reconstruct position from the eye space depth
631        const float3 viewDir = IN.view;
632        const float4 mycolor = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
633        const float eyeSpaceDepth = mycolor.w;
634        const float4 eyeSpacePos = float4(-viewDir * eyeSpaceDepth, 1.0f);
635
636
637        ////////////////
638        //-- calculcate the current projected posiion (also used for next frame)
639       
640        float4 projPos = mul(modelViewProj, eyeSpacePos);
641        const float invw = 1.0f / projPos.w;
642        projPos *= invw;
643       
644        //const float radiusMult = kernelRadius;
645        //const float radiusMult = 3e-2;
646        const float radiusMult = kernelRadius * invw;
647       
648#ifdef PERFORMANCE_TEST
649
650        float3 diffVec = tex2Dlod(attribsTex, float4(IN.texCoord, 0, 0)).xyz;
651
652        const float sqrMoveSpeed = SqrLen(diffVec);
653        const bool isMovingObject = (sqrMoveSpeed > DYNAMIC_OBJECTS_THRESHOLD);
654
655       
656        /////////////////
657        //-- compute temporal reprojection
658
659        float3 temporalVals = Reproject(eyeSpacePos, eyeSpaceDepth, IN.texCoord, oldEyePos,
660                                        oldTex, oldModelViewProj,
661                                                                        colors,
662                                                                        projPos.xyz,
663                                                                        invw,
664                                                                        oldbl, oldbr, oldtl, oldtr,
665                                                                        diffVec
666                                                                        );
667       
668        const float oldSsao = temporalVals.x;
669       
670        float oldWeight = temporalVals.y;
671        float oldIdx = temporalCoherence > 1 ? temporalVals.z : 0;
672        //float oldIdx = temporalVals.z;
673       
674#else
675
676        const float3 diffVec      = float3(.0f);
677        const bool isMovingObject = false;
678        const float oldSsao       = .0f;
679       
680        float oldWeight = .0f;
681        float oldIdx    = .0f;
682       
683#endif
684
685        float3 ao;
686        //$$temp matt
687        oldIdx = dummyIdx;
688
689        // cull background note: this should be done with the stencil buffer
690        if (eyeSpaceDepth < DEPTH_THRESHOLD)
691        {
692#ifdef TRYOUT
693                ao = ssao(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz,
694                              radiusMult, bl, br, tl, tr, normalize(viewDir),
695                              oldWeight, sampleIntensity, isMovingObject, oldIdx);
696#else
697
698                ao = ssao(IN, colors, noiseTex, dummySamples, samples,
699                              normal, eyeSpacePos.xyz, radiusMult, bl,
700                              br, tl, tr, normalize(viewDir),
701                              oldWeight, sampleIntensity, isMovingObject, oldIdx,
702                              attribsTex, mycolor.xyz);
703#endif                           
704        }
705        else
706        {
707                 ao = float3(1.0f);
708        }
709
710
711#ifdef PERFORMANCE_TEST
712
713        ///////////
714        //-- check if we have to reset pixel because one of the sample points was invalid
715        //-- only do this if the current pixel does not belong to a moving object
716
717        // the weight equals the number of sampled shot in this pass
718        const float newWeight = ao.z;
719        // completely reset the ao in this pixel
720        const float completelyResetThres = 20.0f;
721        // don't fully reset the ao in this pixel, but give low weight to old solution
722        const float partlyResetThres = 1.0f;
723       
724        // the new index for the next frame
725        float newIdx;
726        // the new weight for the next frame
727        float combinedWeight;
728
729        // don't check for moving objects, otherwise almost no coherence
730        if (ao.y > completelyResetThres)
731        {
732                oldWeight = newIdx = .0f;
733        }
734        else
735        {
736                newIdx = oldIdx + newWeight;
737        }
738
739        if (ao.y > partlyResetThres)
740        {
741                const float factor = 3.0f;
742
743                oldWeight = min(oldWeight, factor * NUM_SAMPLES);
744                if (newIdx >= factor * NUM_SAMPLES)
745                {
746                        newIdx = .0f;
747                        //oldWeight = .0f;
748                }
749
750                //combinedWeight = oldWeight;
751        }
752
753        // the new weight for the next frame
754        combinedWeight = clamp(newWeight + oldWeight, .0f, temporalCoherence);
755
756
757        //////////
758        //-- blend ao between old and new samples (and avoid division by zero)
759
760        OUT.illum_col.x = ao.x;// * newWeight + oldSsao * oldWeight;
761        //OUT.illum_col.x /= (newWeight + oldWeight);
762
763        OUT.illum_col.y = combinedWeight;
764        OUT.illum_col.z = newIdx; // the new index
765        OUT.illum_col.w = eyeSpaceDepth;
766
767#else
768
769        OUT.illum_col.x = ao.x;
770        OUT.illum_col.w = eyeSpaceDepth;
771       
772#endif
773
774        return OUT;
775}
Note: See TracBrowser for help on using the repository browser.