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

Revision 3345, 19.2 KB checked in by mattausch, 15 years ago (diff)

trying to reduce render targets but something srange

RevLine 
[2884]1#include "../shaderenv.h"
[3227]2#include "common.h"
[2884]3
[2881]4////////////////////
5// Screen Spaced Ambient Occlusion shader
6// based on shader of Alexander Kusternig
7
[3144]8
[3106]9#define USE_EYESPACE_DEPTH 1
[3105]10
11
[2881]12struct fragment
13{
[2889]14        float2 texCoord: TEXCOORD0;
15        float3 view: TEXCOORD1;
[2881]16};
17
18
[3325]19struct pixel2
20{
21        float4 illum_col: COLOR0;
[3345]22        //float4 col: COLOR1;
[3325]23};
24
25
[3247]26// this function is inspired from the paper of shamulgaan in order
27// to get a physical expression for the occlusion culling
[3081]28inline float occlusionPower(float radius, float dist)
29{
30        return 6.283185307179586476925286766559f * (1.0f - cos(asin(radius / dist)));
31}
32
33
[3159]34
[2992]35// reconstruct world space position
[3155]36inline float3 ReconstructSamplePos(float eyeSpaceDepth,
[3017]37                                                                   float2 texcoord,
38                                                                   float3 bl, float3 br, float3 tl, float3 tr)
[2988]39{
[3097]40        float3 viewVec = Interpol(texcoord, bl, br, tl, tr);
[3017]41        float3 samplePos = -viewVec * eyeSpaceDepth;
42
[2999]43        return samplePos;
[2988]44}
45
46
[3318]47float ComputeConvergence(uniform sampler2D tex, float2 texCoord, float2 res)
48{
49        // get the minimum convergence by exactly sampling the 4 surrounding
50        // texels in the old texture, otherwise flickering because convergence
51        // will be interpolated when upsampling and filter size does not match!
[3087]52
[3319]53        const float2 invRes = float2(1.0f / res.x, 1.0f / res.y);
[3318]54
55        // get position exactly between texel centers
[3321]56        float2 center = (floor(texCoord * res) + float2(.5f)) * texCoord;
[3318]57        //center.x = (floor(texCoord.x * res.x - .5f) + 1.0f) / res.x;
58        //center.y = (floor(texCoord.y * res.y - .5f) + 1.0f) / res.y;
59        //center.y = (floor(texCoord.y * res.y) + .5f) * yOffs;
60
61        /*texelCenterConv.x = tex2Dlod(tex, float4(center + float2( xoffs,  yoffs), 0, 0)).y;
62        texelCenterConv.y = tex2Dlod(tex, float4(center + float2( xoffs, -yoffs), 0, 0)).y;
63        texelCenterConv.z = tex2Dlod(tex, float4(center + float2(-xoffs, -yoffs), 0, 0)).y;
64        texelCenterConv.w = tex2Dlod(tex, float4(center + float2(-xoffs,  yoffs), 0, 0)).y;
65
66        const float m1 = min(texelCenterConv.x, texelCenterConv.y);
67        const float m2 = min(texelCenterConv.z, texelCenterConv.w);
68
69        const float convergence = min(m1, m2);*/
70
[3319]71        //const float convergence = tex2Dlod(tex, float4(center, 0, 0)).y;
72        const float convergence = tex2Dlod(tex, float4(texCoord, 0, 0)).y;
[3318]73
74        return convergence;
75}
76
[3115]77/** This shader computes the reprojection and stores
[3155]78        the ssao value of the old pixel as well as the
79        weight of the pixel in the new frame.
[3082]80*/
[3324]81inline float3 Reproject(float4 worldPos,
82                                                float eyeSpaceDepth,
83                                                float2 texcoord0,
84                                                float3 oldEyePos,
85                                                sampler2D oldTex,
86                                                float4x4 oldModelViewProj,
87                                                sampler2D colors,
88                                                float3 projPos,
89                                                float invW,
90                                                float3 oldbl,
91                                                float3 oldbr,
92                                                float3 oldtl,
93                                                float3 oldtr,
94                                                float3 diffVec
95                                                )
[3082]96{
[3113]97        // compute position from old frame for dynamic objects + translational portion
[3133]98        const float3 translatedPos = diffVec - oldEyePos + worldPos.xyz;
[3111]99
[3082]100
[3109]101        /////////////////
102        //-- reproject into old frame and calculate texture position of sample in old frame
103
104        // note: the old model view matrix only holds the view orientation part
[3115]105        float4 backProjPos = mul(oldModelViewProj, float4(translatedPos, 1.0f));
[3083]106        backProjPos /= backProjPos.w;
[3109]107       
[3082]108        // fit from unit cube into 0 .. 1
[3085]109        const float2 oldTexCoords = backProjPos.xy * 0.5f + 0.5f;
[3082]110        // retrieve the sample from the last frame
[3095]111        const float4 oldPixel = tex2Dlod(oldTex, float4(oldTexCoords, .0f, .0f));
[3105]112
[3204]113        // the ssao value in the old frame
114        const float ssao = oldPixel.x;
115
[3095]116        // calculate eye space position of sample in old frame
117        const float oldEyeSpaceDepth = oldPixel.w;
[3082]118
[3345]119        // vector from eye pos to old sample
[3097]120        const float3 viewVec = Interpol(oldTexCoords, oldbl, oldbr, oldtl, oldtr);
[3109]121        const float invLen = 1.0f / length(viewVec);
[3115]122        const float projectedEyeSpaceDepth = invLen * length(translatedPos);
[3137]123        //const float projectedEyeSpaceDepth = length(translatedPos);
[3099]124       
[3109]125        const float depthDif = abs(1.0f - oldEyeSpaceDepth / projectedEyeSpaceDepth);
[3106]126
[3225]127        // the weight of the accumulated samples from the previous frames
[3204]128        float w;
[3325]129        float idx;
[3204]130
[3341]131
[3204]132        //////////////
133        //-- reuse old value only if it was still valid in the old frame
134
[3192]135        if (1
[3225]136                && (oldTexCoords.x > 0) && (oldTexCoords.x < 1.0f)
137                && (oldTexCoords.y > 0) && (oldTexCoords.y < 1.0f)
[3103]138                && (depthDif <= MIN_DEPTH_DIFF)
[3082]139                )
140        {
[3204]141                // pixel valid => retrieve the convergence weight
[3318]142                /*float w1 = tex2Dlod(oldTex, float4(oldTexCoords + float2(0.5f / 1024.0f, 0), .0f, .0f)).y;
[3316]143                float w2 = tex2Dlod(oldTex, float4(oldTexCoords - float2(0.5f / 1024.0f, 0), .0f, .0f)).y;
144                float w3 = tex2Dlod(oldTex, float4(oldTexCoords + float2(0, 0.5f / 768.0f), .0f, .0f)).y;
145                float w4 = tex2Dlod(oldTex, float4(oldTexCoords - float2(0, 0.5f / 768.0f), .0f, .0f)).y;
146
[3318]147                w = min(min(w1, w2), min(w3, w4));*/
148               
[3319]149                //w = ComputeConvergence(oldTex, oldTexCoords, float2(1024.0f, 768.0f));
[3345]150                w = floor(oldPixel.y);
151                //w = oldPixel.y;
[3325]152                idx = floor(oldPixel.z);
[3082]153        }
154        else
155        {       
[3345]156                w = .0f;
[3325]157                idx = .0f;
[3082]158        }
[3087]159
[3324]160        return float3(ssao, w, idx);
[3082]161}
162
163
[3320]164/** The ssao shader returning the an intensity value between 0 and 1.
165        This version of the ssao shader uses the dotproduct between
166        pixel-to-sample direction and sample normal as weight.
167
168    The algorithm works like the following:
169        1) Check in a circular area around the current position.
170        2) Shoot vectors to the positions there, and check the angle to these positions.
171        3) Summing up these angles gives an estimation of the occlusion at the current position.
[2881]172*/
[3193]173float3 ssao2(fragment IN,
[3150]174                         sampler2D colors,
175                         sampler2D noiseTex,
[3324]176                         sampler2D samples,
[3150]177                         float3 normal,
178                         float3 centerPosition,
[3331]179                         float radius,
[3150]180                         float3 bl,
181                         float3 br,
182                         float3 tl,
183                         float3 tr,
184                         float3 viewDir,
[3320]185                         float convergence,
186                         float sampleIntensity,
187                         bool isMovingObject,
[3324]188                         sampler2D normalTex,
[3325]189                         float idx
[3150]190                         )
191{
192        float total_ao = .0f;
[3320]193        float validSamples = .0f;
[3150]194        float numSamples = .0f;
195
[3313]196        for (int i = 0; i < NUM_SAMPLES; ++ i)
[3150]197        {
[3320]198                float2 offset;
[3150]199
[3329]200                const float2 ssaoOffset =
201                        tex2Dlod(samples, float4((0.5f + i + idx) / NUM_PRECOMPUTED_SAMPLES, 0.5f, .0f, .0f)).xy;
[3324]202
[3150]203                ////////////////////
[3320]204                //-- add random noise: reflect around random normal vector
205                //-- (affects performance for some reason!)
[3150]206
[3328]207                if (convergence < SSAO_CONVERGENCE_THRESHOLD)
[3320]208                {
209                        float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
210                        //offset = myreflect(samples[i], mynoise);
[3324]211                        //offset = myrotate(samples[i], mynoise.x);
212                        offset = myrotate(ssaoOffset, mynoise.x);
[3320]213                }
214                else
215                {
[3324]216                        offset = ssaoOffset;
[3320]217                }
218               
[3150]219                // weight with projected coordinate to reach similar kernel size for near and far
[3331]220                const float2 texcoord = IN.texCoord.xy + offset * radius;
[3150]221
[3320]222                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
[3155]223                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
[3320]224               
[3150]225
226                ////////////////
227                //-- compute contribution of sample using the direction and angle
228
229                float3 dirSample = samplePos - centerPosition;
230
[3329]231                const float minDist = 1e-6f;
[3331]232                const float delta = 1e-3f;
[3199]233
[3329]234                const float lengthToSample = length(dirSample);
[3331]235                const float sampleWeight = 1.0f / (lengthToSample + delta);
[3320]236
[3329]237                dirSample /= max(lengthToSample, minDist); // normalize
[3150]238
[3329]239
[3150]240                // angle between current normal and direction to sample controls AO intensity.
[3329]241                const float cosAngle = dot(dirSample, normal);
[3320]242
243                // the normal of the current sample
[3329]244                const float3 sampleNormal = normalize(tex2Dlod(normalTex, float4(texcoord, 0, 0)).xyz);
245               
[3320]246                // angle between current normal and direction to sample controls AO intensity.
[3330]247                //const float cosAngle2 = dot(-dirSample, sampleNormal);
[3339]248                const float cosAngle2 = .5f + dot(sampleNormal, -normal) * .5f;
[3330]249
[3329]250                dirSample *= minDist;
251                const float aoContrib = sampleIntensity * sampleWeight;
[3320]252
[3150]253                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
[3339]254                //total_ao += max(cosAngle, .0f) * max(cosAngle2, .0f) * aoContrib;
255                total_ao += max(cosAngle, .0f) * cosAngle2 * aoContrib;
[3150]256
[3320]257                ++ numSamples;
[3150]258
[3157]259                // check if the samples have been valid in the last frame
[3320]260                // only mark sample as invalid if in the last / current frame
261                // they possibly have any influence on the ao
[3203]262
[3320]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
[3328]270#if 1
[3320]271                const float tooFarAway = step(0.5f, lengthToSample - changeFactor);
[3321]272                const float partlyResetThres = 1.0f;
[3329]273
[3328]274                if (pixelValid <= partlyResetThres)
[3320]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;
[3328]291                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
[3320]292                }
293#endif
[3150]294        }
295
[3320]296        // "normalize" ao contribution
[3193]297        total_ao /= numSamples;
298
[3227]299#if 1
[3225]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);
[3320]303        total_ao *= viewCorrection;
[3225]304#endif
305
[3320]306        //return float3(total_ao, validSamples, numSamples);
307        return float3(min(1.0f, total_ao), validSamples, numSamples);
[3150]308}
309
310
[3151]311/** The ssao shader returning the an intensity value between 0 and 1.
312        This version of the ssao shader uses the dotproduct between
313        pixel-to-sample direction and sample normal as weight.
[3204]314
315    The algorithm works like the following:
316        1) Check in a circular area around the current position.
317        2) Shoot vectors to the positions there, and check the angle to these positions.
318        3) Summing up these angles gives an estimation of the occlusion at the current position.
[3150]319*/
[3192]320float3 ssao(fragment IN,
[3117]321                        sampler2D colors,
322                        sampler2D noiseTex,
[3329]323                        sampler2D samples,
[3117]324                        float3 normal,
325                        float3 centerPosition,
[3331]326                        float radius,
[3117]327                        float3 bl,
328                        float3 br,
329                        float3 tl,
330                        float3 tr,
[3192]331                        float3 viewDir,
[3230]332                        float convergence,
[3213]333                        float sampleIntensity,
[3329]334                        bool isMovingObject,
335                        float oldIdx
[3083]336                        )
[2881]337{
[3084]338        float total_ao = .0f;
[3192]339        float validSamples = .0f;
[3084]340        float numSamples = .0f;
[3313]341
[2881]342        for (int i = 0; i < NUM_SAMPLES; ++ i)
343        {
[3230]344                float2 offset;
[2881]345
[3329]346                const float2 ssaoOffset =
347                        tex2Dlod(samples, float4((0.5f + i + oldIdx) / NUM_PRECOMPUTED_SAMPLES, 0.5f, .0f, .0f)).xy;
348
[2881]349                ////////////////////
[3204]350                //-- add random noise: reflect around random normal vector
[3227]351                //-- (affects performance for some reason!)
[2985]352
[3311]353                if (convergence < SSAO_CONVERGENCE_THRESHOLD)
[3230]354                {
[3313]355                        float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy;
[3284]356                        //offset = myreflect(samples[i], mynoise);
[3329]357                        //offset = myrotate(samples[i], mynoise.x);
358                        offset = myrotate(ssaoOffset, mynoise.x);
[3230]359                }
360                else
361                {
[3329]362                        offset = ssaoOffset;
[3230]363                }
[3329]364
365
[2881]366                // weight with projected coordinate to reach similar kernel size for near and far
[3331]367                const float2 texcoord = IN.texCoord.xy + offset * radius;
[2881]368
[3203]369                const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f));
[3155]370                const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr);
[3150]371               
[2989]372
[3017]373                ////////////////
374                //-- compute contribution of sample using the direction and angle
[2881]375
[3017]376                float3 dirSample = samplePos - centerPosition;
[2999]377
[3329]378                const float minDist = 1e-6f;
[3344]379                const float eps = 1e-3f;
[3319]380
[3329]381                const float lengthToSample = length(dirSample);
[3344]382                const float sampleWeight = 1.0f / max(lengthToSample, eps);
[3197]383
[3329]384                dirSample /= max(length(dirSample), minDist); // normalize
[3095]385
[2885]386                // angle between current normal and direction to sample controls AO intensity.
[3329]387                const float cosAngle = dot(dirSample, normal);
[3227]388
389                //const float aoContrib = sampleIntensity / sqrLen;
[3329]390                const float aoContrib = sampleIntensity * sampleWeight;
[3089]391                //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f;
[2881]392
[3329]393                total_ao += max(cosAngle, .0f) * aoContrib;
[3157]394
[3206]395                ++ numSamples;
[3340]396
[3331]397#ifdef PERFORMANCE_TEST
[3157]398                // check if the samples have been valid in the last frame
[3213]399                // only mark sample as invalid if in the last / current frame
400                // they possibly have any influence on the ao
[3319]401
[3206]402                const float changeFactor = sampleColor.y;
403                const float pixelValid = sampleColor.x;
[3204]404
[3319]405                // hack:
[3213]406                // we check if the sample could have been near enough to the current pixel
[3319]407                // or if the angle is small enough
[3213]408                // to have any influence in the current or last frame
[3331]409
[3328]410#if 1
[3321]411                const float partlyResetThres = 1.0f;
412
[3313]413                const float tooFarAway = step(0.5f, lengthToSample - changeFactor);
[3321]414                if (0)//pixelValid <= partlyResetThres)
[3319]415                        validSamples = max(validSamples, pixelValid * (1.0f - tooFarAway) * step(-0.1f, cosAngle));
416                else
417                        validSamples = max(validSamples, pixelValid);
[3314]418#endif
[3192]419
[3227]420#ifdef USE_GTX
[3213]421                // we can bail out early and use a minimal #samples)
422                // if some conditions are met as long as the hardware supports it
[3230]423                if (numSamples >= MIN_SAMPLES)
[3213]424                {
[3313]425                        //break;
[3213]426                        // if the pixel belongs to a static object and all the samples stay valid in the current frame
[3319]427                        if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break;
[3313]428                        // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high
429                        // (=> there was no discontinuity recently)
[3319]430                        //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break;
[3329]431                        else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break;
[3213]432                }
433#endif
[3331]434
435#endif // PERFORMANCE_TEST
[2881]436        }
437
[3225]438        // "normalize" ao contribution
[3192]439        total_ao /= numSamples;
440
[3225]441#if 1
442        // if surface normal perpenticular to view dir, approx. half of the samples will not count
443        // => compensate for this (on the other hand, projected sampling area could be larger!)
444        const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f);
445        total_ao *= viewCorrection;
446#endif
447
[3271]448        //return float3(total_ao, validSamples, numSamples);
449        return float3(min(1.0f, total_ao), validSamples, numSamples);
[2881]450}
451
[3121]452
[3150]453
[2881]454/** The mrt shader for screen space ambient occlusion
455*/
[3325]456pixel2 main(fragment IN,
457                        uniform sampler2D colors,
458                        uniform sampler2D normals,
459                        uniform sampler2D noiseTex,
460                        uniform sampler2D samples,
461                        uniform sampler2D oldTex,
462                        uniform float4x4 modelViewProj,
463                        uniform float4x4 oldModelViewProj,
464                        uniform float temporalCoherence,
465                        uniform float3 bl,
466                        uniform float3 br,
467                        uniform float3 tl,
468                        uniform float3 tr,
469                        uniform float3 oldEyePos,
470                        uniform float3 oldbl,
471                        uniform float3 oldbr,
472                        uniform float3 oldtl,
473                        uniform float3 oldtr,
474                        uniform sampler2D attribsTex,
475                        uniform float kernelRadius,
476                        uniform float sampleIntensity
477                        )
[2881]478{
[3325]479        pixel2 OUT;
[2881]480
[3167]481        //const float3 normal = normalize(tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz);
482        const float3 normal = tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz;
[2975]483
[3082]484        // reconstruct position from the eye space depth
[3097]485        const float3 viewDir = IN.view;
[3089]486        const float eyeSpaceDepth = tex2Dlod(colors, float4(IN.texCoord, 0, 0)).w;
[3097]487        const float4 eyeSpacePos = float4(-viewDir * eyeSpaceDepth, 1.0f);
[3014]488
[3341]489
[3017]490        ////////////////
[3080]491        //-- calculcate the current projected posiion (also used for next frame)
[3017]492       
[3094]493        float4 projPos = mul(modelViewProj, eyeSpacePos);
[3112]494        const float invw = 1.0f / projPos.w;
495        projPos *= invw;
[3331]496       
497        //const float radiusMult = kernelRadius;
[3342]498        //const float radiusMult = 3e-2;
499        const float radiusMult = kernelRadius * invw;
[3331]500       
[3342]501#ifdef PERFORMANCE_TEST
[3121]502
[3345]503        float3 diffVec = tex2Dlod(attribsTex, float4(IN.texCoord, .0f, .0f)).xyz;
[3331]504
[3213]505        const float sqrMoveSpeed = SqrLen(diffVec);
506        const bool isMovingObject = (sqrMoveSpeed > DYNAMIC_OBJECTS_THRESHOLD);
507
[3017]508       
[3121]509        /////////////////
510        //-- compute temporal reprojection
511
[3324]512        float3 temporalVals = Reproject(eyeSpacePos, eyeSpaceDepth, IN.texCoord, oldEyePos,
[3316]513                                        oldTex, oldModelViewProj,
514                                                                        colors,
515                                                                        projPos.xyz,
516                                                                        invw,
517                                                                        oldbl, oldbr, oldtl, oldtr,
518                                                                        diffVec
519                                                                        );
[3331]520       
[3121]521        const float oldSsao = temporalVals.x;
[3328]522       
[3345]523        float oldIdx = temporalCoherence > 1 ? temporalVals.y : .0f;
524        //float oldWeight = temporalVals.y;
525        float oldWeight = clamp(oldIdx, 0, temporalCoherence);
526
[3331]527#else
528
529        const bool isMovingObject = false;
[3345]530        const float oldSsao = .0f;
[3331]531       
[3345]532        float oldWeight = .0f;
533        float oldIdx = .0f;
[3331]534       
535#endif
536
[3192]537        float3 ao;
[3137]538
[3192]539        // cull background note: this should be done with the stencil buffer
[3304]540        if (eyeSpaceDepth < DEPTH_THRESHOLD)
[3192]541        {
[3340]542                if (1)
[3327]543                {
[3329]544                        ao = ssao(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz,
[3331]545                                      radiusMult, bl, br, tl, tr, normalize(viewDir),
[3329]546                                          oldWeight, sampleIntensity, isMovingObject, oldIdx);
[3327]547                }
[3326]548                else
[3327]549                {
[3331]550                        ao = ssao2(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz, radiusMult,
[3330]551                                   bl, br, tl, tr, normalize(viewDir), oldWeight, sampleIntensity,
552                                           isMovingObject, normals, oldIdx);
[3327]553                }
[3192]554        }
555        else
556        {
[3198]557                 ao = float3(1.0f, 1.0f, 1.0f);
[3192]558        }
[3122]559
[3331]560
[3342]561#ifdef PERFORMANCE_TEST
562
[3213]563        ///////////
564        //-- check if we have to reset pixel because one of the sample points was invalid
565        //-- only do this if the current pixel does not belong to a moving object
[3205]566
[3213]567        // the weight equals the number of sampled shot in this pass
568        const float newWeight = ao.z;
569
[3225]570        // completely reset the ao in this pixel
[3306]571        const float completelyResetThres = 20.0f;
[3225]572        // don't fully reset the ao in this pixel, but give low weight to old solution
[3213]573        const float partlyResetThres = 1.0f;
574       
[3325]575        // don't check for moving objects, otherwise almost no coherence
[3328]576        if (!isMovingObject)
[3206]577        {
[3213]578                if (ao.y > completelyResetThres)
[3225]579                {
[3325]580                        oldWeight = .0f;
581                        oldIdx = .0f;
[3225]582                }
[3213]583                else if (ao.y > partlyResetThres)
[3225]584                {
[3345]585                        oldWeight = min(oldWeight, 4.0f * NUM_SAMPLES); oldIdx = oldWeight;
586                        //oldWeight = .0f; oldIdx = .0f;
[3225]587                }
[3328]588        }
[3206]589
[3326]590
[3213]591        //////////
592        //-- blend ao between old and new samples (and avoid division by zero)
[3225]593
[3325]594        OUT.illum_col.x = (ao.x * newWeight + oldSsao * oldWeight);
[3311]595        OUT.illum_col.x /= (newWeight + oldWeight);
[3213]596
[3227]597        // the new weight for the next frame
[3345]598        const float newIdx = newWeight + oldIdx;
599        //const float combinedWeight = clamp(newIdx, .0f, temporalCoherence);
600        const float combinedWeight = clamp(newIdx, .0f, min(newWeight + oldWeight, temporalCoherence));
[3313]601
[3345]602        //OUT.illum_col.y = combinedWeight;
603        OUT.illum_col.y = newIdx; // the new index
[3325]604        OUT.illum_col.w = eyeSpaceDepth;
605
[3327]606        //if (OUT.illum_col.z > 1000) OUT.illum_col.z = 0;
607
[3326]608        // this value can be used to check if this pixel belongs to a moving object
[3345]609        //OUT.col.x = SqrLen(diffVec);
610        OUT.illum_col.z = SqrLen(diffVec);
[3326]611
[3331]612#else
613
614        OUT.illum_col.x = ao.x;
615        OUT.illum_col.w = eyeSpaceDepth;
616       
617#endif
618
[2881]619        return OUT;
[3326]620}
Note: See TracBrowser for help on using the repository browser.