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

Revision 3019, 7.4 KB checked in by mattausch, 16 years ago (diff)

detected memory leaks mainly in shadowmapping!!
strange problems with deferred rendering, seems to be uninitialized sometimes (solved?)

RevLine 
[2884]1#include "../shaderenv.h"
2
[2881]3////////////////////
4// Screen Spaced Ambient Occlusion shader
5// based on shader of Alexander Kusternig
6
7
[3006]8#define USE_EYE_SPACE_DEPTH 1
[3001]9
10
[2881]11struct fragment
12{
[2889]13        float2 texCoord: TEXCOORD0;
14        float3 view: TEXCOORD1;
[2881]15};
16
17
18struct pixel
19{
20        float4 illum_col: COLOR0;
21};
22
23
[2990]24inline float2 myreflect(float2 pt, float2 n)
[2881]25{
26        // distance to plane
27        float d = dot(n, pt);
28        // reflect around plane
29        float2 rpt = pt - d * 2.0f * n;
[2886]30
[2881]31        return rpt;
32}
33
34
[2990]35inline float3 Interpol(float2 w, float3 bl, float3 br, float3 tl, float3 tr)
[2986]36{
[2991]37        float3 x1 = lerp(bl, tl, w.y);
38        float3 x2 = lerp(br, tr, w.y);
39        float3 v = lerp(x1, x2, w.x);
[2987]40
41        return v;
42}
43
[2988]44
[2992]45// reconstruct world space position
[3017]46inline float3 ReconstructSamplePos(uniform sampler2D colors,
47                                                                   float2 texcoord,
48                                                                   float3 bl, float3 br, float3 tl, float3 tr)
[2988]49{
[3019]50        //const float eyeSpaceDepth = tex2Dlod(colors, float4(texcoord, 0, 0)).w;
51        const float eyeSpaceDepth = tex2D(colors, texcoord).w;
[3017]52        float3 viewVec = Interpol(texcoord, bl, br, tl, tr);
53        float3 samplePos = -viewVec * eyeSpaceDepth;
54
[2999]55        return samplePos;
[2988]56}
57
58
[2881]59/** The ssao shader returning the an intensity value between 0 and 1
60*/
[2904]61float2 ssao(fragment IN,
[2985]62                   uniform sampler2D colors,
[2881]63                   uniform sampler2D noiseTexture,
64                   uniform float2 samples[NUM_SAMPLES],
65                   uniform float3 currentNormal,
[3006]66                   uniform float3 centerPosition,
[2985]67                   uniform float scaleFactor,
[2986]68                   uniform float3 bl,
69                   uniform float3 br,
70                   uniform float3 tl,
[3017]71                   uniform float3 tr,
72                   uniform float3 viewDir
[2881]73                   )
74{
75        // Check in a circular area around the current position.
76        // Shoot vectors to the positions there, and check the angle to these positions.
77        // Summing up these angles gives an estimation of the occlusion at the current position.
78
79        float total_ao = 0.0;
[2904]80        float numSamples = 0;
[2881]81
[2986]82
[2881]83        for (int i = 0; i < NUM_SAMPLES; ++ i)
84        {
[2892]85                const float2 offset = samples[i];
[2881]86
[2903]87#if 1
[2881]88                ////////////////////
[2903]89                // add random noise: reflect around random normal vector (warning: slow!)
[2985]90
[3017]91                float2 mynoise = tex2D(noiseTexture, IN.texCoord).xy;
[2892]92                const float2 offsetTransformed = myreflect(offset, mynoise);
[2903]93#else
94                const float2 offsetTransformed = offset;
95#endif
[2881]96                // weight with projected coordinate to reach similar kernel size for near and far
[3019]97                const float2 texcoord = IN.texCoord.xy + offsetTransformed * scaleFactor;
[2881]98
[3019]99                //if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f)) ++ numSamples;
[2904]100
[3017]101                const float3 samplePos = ReconstructSamplePos(colors, texcoord, bl, br, tl, tr);
[2989]102
[2881]103
[3017]104                ////////////////
105                //-- compute contribution of sample using the direction and angle
[2881]106
[3017]107                float3 dirSample = samplePos - centerPosition;
[3019]108                const float magSample = length(dirSample);
109                // normalize
110                dirSample /= magSample;
[2999]111
[2885]112                // angle between current normal and direction to sample controls AO intensity.
[3019]113                const float cosAngle = max(dot(dirSample, currentNormal), 0.0f);
[2881]114
[2979]115                // the distance_scale offset is used to avoid singularity that occurs at global illumination when
116                // the distance to a sample approaches zero
[3019]117                const float intensity = SAMPLE_INTENSITY / (DISTANCE_SCALE + magSample * magSample);
[2881]118
[3017]119#if 1
[2885]120                // if surface normal perpenticular to view dir, approx. half of the samples will not count
121                // => compensate for this (on the other hand, projected sampling area could be larger!)
[3017]122                const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * dot(viewDir, currentNormal);
123                total_ao += cosAngle * intensity * viewCorrection;
124#else
125                total_ao += cosAngle * intensity;
[2911]126#endif
[2881]127        }
128
[2904]129        return float2(max(0.0f, 1.0f - total_ao), numSamples);
[2881]130}
131
[3017]132#pragma position_invariant main
[2881]133
134/** The mrt shader for screen space ambient occlusion
135*/
136pixel main(fragment IN,
137                   uniform sampler2D colors,
138                   uniform sampler2D normals,
139                   uniform sampler2D noiseTexture,
140                   uniform float2 samples[NUM_SAMPLES],
141                   uniform sampler2D oldTex,
142                   const uniform float4x4 oldModelViewProj,
[3004]143                   const uniform float4x4 modelViewProj,
[2985]144                   uniform float temporalCoherence,
[2986]145                   uniform float3 eyePos,
146                   uniform float3 bl,
147                   uniform float3 br,
148                   uniform float3 tl,
[2997]149                   uniform float3 tr
[2881]150                   )
151{
152        pixel OUT;
153
[3006]154        float4 norm = tex2Dlod(normals, float4(IN.texCoord, 0 ,0));
[3017]155        const float3 normal = normalize(norm.xyz);
[2975]156
[2993]157        /// reconstruct position from the eye space depth
[3001]158        float3 viewDir = IN.view;
[3006]159        const float eyeDepth = tex2Dlod(colors, float4(IN.texCoord, 0, 0)).w;
[3014]160        const float3 eyeSpacePos = -viewDir * eyeDepth;
[3017]161        const float3 centerPosition = eyePos + eyeSpacePos;
[3014]162
[3017]163        float4 realPos = float4(centerPosition, 1.0f);
[3001]164
[3016]165
[3017]166        ////////////////
167        //-- calculcate the current projected depth for next frame
168       
169        float4 currentPos = mul(modelViewProj, realPos);
170       
171        const float w = SAMPLE_RADIUS / currentPos.w;
172        currentPos /= currentPos.w;
173       
174        const float currentDepth = currentPos.z * 1e-3f;
[2993]175
[3017]176        const float2 ao = ssao(IN, colors, noiseTexture, samples, normal, eyeSpacePos, w, bl, br, tl, tr, normalize(viewDir));
[3005]177
[3000]178
[3005]179        /////////////////
180        //-- compute temporally smoothing
181
182
[3017]183        // reproject new frame into old one
[3004]184       
185        // calculate projected depth
186        float4 projPos = mul(oldModelViewProj, realPos);
[3005]187        projPos /= projPos.w;
[2881]188
[2996]189        // the current depth projected into the old frame
[3017]190        const float projDepth = projPos.z * 1e-3f;
[2881]191
[2995]192        // fit from unit cube into 0 .. 1
[3017]193        const float2 tex = projPos.xy * 0.5f + 0.5f;
[2995]194
[3006]195        // retrieve the sample from the last frame
[2881]196        float4 oldCol = tex2D(oldTex, tex);
197
[3017]198        const float oldDepth = oldCol.z;
199        //const float depthDif = 1.0f - projDepth / oldDepth;
200        const float depthDif = projDepth - oldDepth;
[3006]201
202
[3000]203        //const float oldNumSamples = oldCol.y;
[3017]204        const float oldWeight = clamp(oldCol.y, 0, temporalCoherence);
[2881]205
[2897]206        float newWeight;
[2881]207
[2993]208        // the number of valid samples in this frame
[2999]209        //const float newNumSamples = ao.y;
[2982]210
[2904]211        if (//(temporalCoherence > 0) &&
[2897]212                (tex.x >= 0.0f) && (tex.x < 1.0f) &&
[2881]213                (tex.y >= 0.0f) && (tex.y < 1.0f) &&
[3009]214                (abs(depthDif) < MIN_DEPTH_DIFF)
[2991]215                // if visibility changed in the surrounding area we have to recompute
[2999]216                //&& (oldNumSamples > 0.8f * newNumSamples)
[2904]217                )
[2881]218        {
[2904]219                // increase the weight for convergence
220                newWeight = oldWeight + 1.0f;
[3017]221                OUT.illum_col.x = (ao.x + oldCol.x * oldWeight) / newWeight;
[2904]222                //if (!(oldNumSamples > ao.y - 1.5f)) newWeight = 0;
[2881]223        }
224        else
[2982]225        {       
[3017]226                OUT.illum_col.x = ao.x;
[2897]227                newWeight = 0;
[2881]228        }
229
[3017]230        //OUT.illum_col.y=depthDif;
231        OUT.illum_col.y = newWeight;
232        OUT.illum_col.z = currentDepth;
[2880]233
[2881]234        return OUT;
235}
[2880]236
[2881]237
[3017]238float Filter(float2 texCoord,
239                         uniform sampler2D ssaoTex,
240                         uniform float2 filterOffs[NUM_DOWNSAMPLES],
241                         uniform float filterWeights[NUM_DOWNSAMPLES]
242)
243{
244        float average = .0f;
245        float w = .0f;
246
247        for (int i = 0; i < NUM_DOWNSAMPLES; ++ i)
248        {
249                average += filterWeights[i] * tex2Dlod(ssaoTex, float4(texCoord + filterOffs[i], 0, 0)).x;
250                w += filterWeights[i];
251        }
252
253        average *= 1.0f / (float)w;
254
255        return average;
256}
257
258
[2880]259pixel combine(fragment IN,
260                          uniform sampler2D colors,
[3017]261                          uniform sampler2D ssaoTex,
262                          uniform float2 filterOffs[NUM_DOWNSAMPLES],
263                          uniform float filterWeights[NUM_DOWNSAMPLES]
264                          )
[2880]265{
266        pixel OUT;
267
[3006]268        float4 col = tex2Dlod(colors, float4(IN.texCoord, 0, 0));
[3017]269        float3 ao = tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0));
[2880]270
[3017]271        if (ao.y < 2000.0f)
272                ao.x = Filter(IN.texCoord, ssaoTex, filterOffs, filterWeights);
273
[3016]274        OUT.illum_col = col * ao.x;
[3017]275        //OUT.illum_col.xyz = float3(ao.x,1-ao.y*1e-2f, 0);
[2975]276        OUT.illum_col.w = col.w;
[2880]277
278        return OUT;
[3000]279}
Note: See TracBrowser for help on using the repository browser.