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

Revision 2991, 6.9 KB checked in by mattausch, 16 years ago (diff)

what todo with tone mapping: manually donwsample??
or manually downsample ssao?? or use smaller rendertarget for ssao solution??

RevLine 
[2884]1#include "../shaderenv.h"
2
[2881]3////////////////////
4// Screen Spaced Ambient Occlusion shader
5// based on shader of Alexander Kusternig
6
7
8struct fragment
9{
10         // normalized screen position
11        float4 pos: WPOS;
[2889]12        float2 texCoord: TEXCOORD0;
13        float3 view: TEXCOORD1;
[2881]14};
15
16
17struct pixel
18{
19        float4 illum_col: COLOR0;
20};
21
22
[2990]23inline float2 myreflect(float2 pt, float2 n)
[2881]24{
25        // distance to plane
26        float d = dot(n, pt);
27        // reflect around plane
28        float2 rpt = pt - d * 2.0f * n;
[2886]29
[2881]30        return rpt;
31}
32
33
[2990]34inline float3 Interpol(float2 w, float3 bl, float3 br, float3 tl, float3 tr)
[2986]35{
[2991]36        float3 x1 = lerp(bl, tl, w.y);
37        float3 x2 = lerp(br, tr, w.y);
38        float3 v = lerp(x1, x2, w.x);
[2987]39
40        return v;
41}
42
[2988]43
[2991]44inline float3 ReconstructSamplePosition(float3 eyePos,
45                                                                                uniform sampler2D colors,
46                                                                                float2 texcoord,
47                                                                                float3 bl, float3 br, float3 tl, float3 tr)
[2988]48{
[2990]49        /*float eyeSpaceDepth = tex2Dlod(colors, float4(texcoord, 0, SSAO_MIPMAP_LEVEL)).w;
50               
51        // reconstruct world space position
52        float3 rotView = normalize(Interpol(texcoord, bl, br, tl, tr));
[2991]53        float3 sample_position = eyePos - rotView * eyeSpaceDepth;*/
[2990]54        float3 sample_position = tex2Dlod(colors, float4(texcoord, 0, SSAO_MIPMAP_LEVEL)).xyz;
[2988]55
[2990]56        return sample_position;
[2988]57}
58
59
[2881]60/** The ssao shader returning the an intensity value between 0 and 1
61*/
[2904]62float2 ssao(fragment IN,
[2985]63                   uniform sampler2D colors,
[2881]64                   uniform sampler2D noiseTexture,
65                   uniform float2 samples[NUM_SAMPLES],
66                   uniform float3 currentNormal,
[2974]67                   uniform float4 centerPosition,
[2985]68                   uniform float scaleFactor,
[2990]69                   //uniform float3 viewDir,
[2986]70                   uniform float3 eyePos,
71                   uniform float3 bl,
72                   uniform float3 br,
73                   uniform float3 tl,
[2988]74                   uniform float3 tr
[2881]75                   )
76{
77        // Check in a circular area around the current position.
78        // Shoot vectors to the positions there, and check the angle to these positions.
79        // Summing up these angles gives an estimation of the occlusion at the current position.
80
81        float total_ao = 0.0;
[2904]82        float numSamples = 0;
[2881]83
[2986]84
[2881]85        for (int i = 0; i < NUM_SAMPLES; ++ i)
86        {
[2892]87                const float2 offset = samples[i];
[2881]88
[2903]89#if 1
[2881]90                ////////////////////
[2903]91                // add random noise: reflect around random normal vector (warning: slow!)
[2985]92
[2903]93                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy;
[2892]94                const float2 offsetTransformed = myreflect(offset, mynoise);
[2903]95#else
96                const float2 offsetTransformed = offset;
97#endif
[2881]98                // weight with projected coordinate to reach similar kernel size for near and far
[2974]99                float2 texcoord = IN.texCoord.xy + offsetTransformed * AREA_SIZE * scaleFactor;
[2881]100
[2904]101                if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f))
102                        ++ numSamples;
103
[2991]104                float3 sample_position = ReconstructSamplePosition(eyePos, colors, texcoord, bl, br, tl, tr);
[2989]105
[2881]106                float3 vector_to_sample = sample_position - centerPosition.xyz;
107                const float length_to_sample = length(vector_to_sample);
108
109                float3 direction_to_sample = vector_to_sample / length_to_sample;
110
[2885]111                // angle between current normal and direction to sample controls AO intensity.
[2881]112                const float cos_angle = max(dot(direction_to_sample, currentNormal), 0.0f);
113
[2979]114                // the distance_scale offset is used to avoid singularity that occurs at global illumination when
115                // the distance to a sample approaches zero
[2881]116                const float distance_intensity =
117                        (SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample);
118
[2911]119#if 0
[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!)
[2911]122                const float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal));
123                total_ao += cos_angle * distance_intensity * view_correction;
124#endif
[2887]125                total_ao += cos_angle * distance_intensity;
[2881]126        }
127
[2904]128        return float2(max(0.0f, 1.0f - total_ao), numSamples);
[2890]129        //return saturate(dot(currentViewDir, currentNormal));
[2881]130}
131
132
133/** The mrt shader for screen space ambient occlusion
134*/
135pixel main(fragment IN,
136                   uniform sampler2D colors,
137                   uniform sampler2D positions,
138                   uniform sampler2D normals,
139                   uniform sampler2D noiseTexture,
140                   uniform float2 samples[NUM_SAMPLES],
141                   uniform sampler2D oldTex,
142                   const uniform float4x4 oldModelViewProj,
143                   uniform float maxDepth,
[2985]144                   uniform float temporalCoherence,
[2986]145                   uniform float3 eyePos,
146                   uniform float3 bl,
147                   uniform float3 br,
148                   uniform float3 tl,
149                   uniform float3 tr
[2881]150                   )
151{
152        pixel OUT;
153
154        float4 norm = tex2D(normals, IN.texCoord.xy);
155        float3 normal = normalize(norm.xyz);
[2975]156
[2974]157        // a constant ambient term
158        const float amb = norm.w;
159        // the w coordinate from the persp. projection
160        float w = norm.w;
[2881]161        // the current world position
162        const float4 centerPosition = tex2D(positions, IN.texCoord.xy);
[2990]163       
164        /*
[2989]165        /// the current view direction
166        float3 viewDir = normalize(IN.view);
[2990]167        const float eyeDepth = tex2D(colors, IN.texCoord.xy).w;
[2988]168        float4 centerPosition2;
169        centerPosition2.xyz = eyePos - view2 * eyeDepth;
[2989]170*/
171
[2988]172        // the current depth
[2974]173        const float currentDepth = centerPosition.w;
[2881]174
[2986]175        //const float2 ao = ssao(IN, positions, noiseTexture, samples, normal, centerPosition, w, viewDir, eyePos);
[2991]176        const float2 ao = ssao(IN, positions, noiseTexture, samples, normal, centerPosition, w, eyePos, bl, br, tl, tr);
[2881]177               
178
179        /////////////////
180        //-- compute temporally smoothing
181
182        float4 realPos = centerPosition * maxDepth;
183        realPos.w = 1.0f;
184
[2975]185
186        ///////////
187        //-- reprojection from new frame into old one
188
[2881]189        float4 oldPos = mul(oldModelViewProj, realPos);
190
191        const float newDepth = oldPos.z / oldPos.w;
192
193        float2 tex = (oldPos.xy / oldPos.w) * 0.5f + 0.5f;
194        float4 oldCol = tex2D(oldTex, tex);
195
196        const float oldDepth = oldCol.w;
197        const float depthDif = 1.0f - newDepth / oldDepth;
198
[2897]199        float oldWeight = clamp(oldCol.z, 0, temporalCoherence);
[2904]200        float oldNumSamples = oldCol.y;
201
[2897]202        float newWeight;
[2881]203
[2982]204        float newNumSamples = ao.y;
205
[2904]206        if (//(temporalCoherence > 0) &&
[2897]207                (tex.x >= 0.0f) && (tex.x < 1.0f) &&
[2881]208                (tex.y >= 0.0f) && (tex.y < 1.0f) &&
[2982]209                (abs(depthDif) < 1e-4f)
[2991]210                // if visibility changed in the surrounding area we have to recompute
211                && (oldNumSamples > 0.8f * newNumSamples)
[2982]212                //&& (oldAvgDepth / newAvgDepth > 0.99)
[2904]213                )
[2881]214        {
[2904]215                // increase the weight for convergence
216                newWeight = oldWeight + 1.0f;
217                OUT.illum_col.xy = (ao.xy + oldCol.xy * oldWeight) / newWeight;
218
219                //if (!(oldNumSamples > ao.y - 1.5f)) newWeight = 0;
[2881]220        }
221        else
[2982]222        {       
[2904]223                OUT.illum_col.xy = ao.xy;
[2897]224                newWeight = 0;
[2881]225        }
226
[2897]227        OUT.illum_col.z = newWeight;
[2880]228        OUT.illum_col.w = currentDepth;
229
[2881]230        return OUT;
231}
[2880]232
[2881]233
[2880]234pixel combine(fragment IN,
235                          uniform sampler2D colors,
[2974]236                          uniform sampler2D ssaoTex,
237                          uniform sampler2D positions)
[2880]238{
239        pixel OUT;
240
[2884]241        float4 col = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0));
[2880]242        float4 ao = tex2D(ssaoTex, IN.texCoord.xy);
243
[2990]244        OUT.illum_col = col * ao.x;
245        //OUT.illum_col = float4(ao.x,ao.x,ao.x, ao.w);
[2975]246        OUT.illum_col.w = col.w;
[2880]247
248        return OUT;
[2873]249}
Note: See TracBrowser for help on using the repository browser.