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

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