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??

Line 
1#include "../shaderenv.h"
2
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;
12        float2 texCoord: TEXCOORD0;
13        float3 view: TEXCOORD1;
14};
15
16
17struct pixel
18{
19        float4 illum_col: COLOR0;
20};
21
22
23inline float2 myreflect(float2 pt, float2 n)
24{
25        // distance to plane
26        float d = dot(n, pt);
27        // reflect around plane
28        float2 rpt = pt - d * 2.0f * n;
29
30        return rpt;
31}
32
33
34inline float3 Interpol(float2 w, float3 bl, float3 br, float3 tl, float3 tr)
35{
36        float3 x1 = lerp(bl, tl, w.y);
37        float3 x2 = lerp(br, tr, w.y);
38        float3 v = lerp(x1, x2, w.x);
39
40        return v;
41}
42
43
44inline float3 ReconstructSamplePosition(float3 eyePos,
45                                                                                uniform sampler2D colors,
46                                                                                float2 texcoord,
47                                                                                float3 bl, float3 br, float3 tl, float3 tr)
48{
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));
53        float3 sample_position = eyePos - rotView * eyeSpaceDepth;*/
54        float3 sample_position = tex2Dlod(colors, float4(texcoord, 0, SSAO_MIPMAP_LEVEL)).xyz;
55
56        return sample_position;
57}
58
59
60/** The ssao shader returning the an intensity value between 0 and 1
61*/
62float2 ssao(fragment IN,
63                   uniform sampler2D colors,
64                   uniform sampler2D noiseTexture,
65                   uniform float2 samples[NUM_SAMPLES],
66                   uniform float3 currentNormal,
67                   uniform float4 centerPosition,
68                   uniform float scaleFactor,
69                   //uniform float3 viewDir,
70                   uniform float3 eyePos,
71                   uniform float3 bl,
72                   uniform float3 br,
73                   uniform float3 tl,
74                   uniform float3 tr
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;
82        float numSamples = 0;
83
84
85        for (int i = 0; i < NUM_SAMPLES; ++ i)
86        {
87                const float2 offset = samples[i];
88
89#if 1
90                ////////////////////
91                // add random noise: reflect around random normal vector (warning: slow!)
92
93                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy;
94                const float2 offsetTransformed = myreflect(offset, mynoise);
95#else
96                const float2 offsetTransformed = offset;
97#endif
98                // weight with projected coordinate to reach similar kernel size for near and far
99                float2 texcoord = IN.texCoord.xy + offsetTransformed * AREA_SIZE * scaleFactor;
100
101                if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f))
102                        ++ numSamples;
103
104                float3 sample_position = ReconstructSamplePosition(eyePos, colors, texcoord, bl, br, tl, tr);
105
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
111                // angle between current normal and direction to sample controls AO intensity.
112                const float cos_angle = max(dot(direction_to_sample, currentNormal), 0.0f);
113
114                // the distance_scale offset is used to avoid singularity that occurs at global illumination when
115                // the distance to a sample approaches zero
116                const float distance_intensity =
117                        (SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample);
118
119#if 0
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!)
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
125                total_ao += cos_angle * distance_intensity;
126        }
127
128        return float2(max(0.0f, 1.0f - total_ao), numSamples);
129        //return saturate(dot(currentViewDir, currentNormal));
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,
144                   uniform float temporalCoherence,
145                   uniform float3 eyePos,
146                   uniform float3 bl,
147                   uniform float3 br,
148                   uniform float3 tl,
149                   uniform float3 tr
150                   )
151{
152        pixel OUT;
153
154        float4 norm = tex2D(normals, IN.texCoord.xy);
155        float3 normal = normalize(norm.xyz);
156
157        // a constant ambient term
158        const float amb = norm.w;
159        // the w coordinate from the persp. projection
160        float w = norm.w;
161        // the current world position
162        const float4 centerPosition = tex2D(positions, IN.texCoord.xy);
163       
164        /*
165        /// the current view direction
166        float3 viewDir = normalize(IN.view);
167        const float eyeDepth = tex2D(colors, IN.texCoord.xy).w;
168        float4 centerPosition2;
169        centerPosition2.xyz = eyePos - view2 * eyeDepth;
170*/
171
172        // the current depth
173        const float currentDepth = centerPosition.w;
174
175        //const float2 ao = ssao(IN, positions, noiseTexture, samples, normal, centerPosition, w, viewDir, eyePos);
176        const float2 ao = ssao(IN, positions, noiseTexture, samples, normal, centerPosition, w, eyePos, bl, br, tl, tr);
177               
178
179        /////////////////
180        //-- compute temporally smoothing
181
182        float4 realPos = centerPosition * maxDepth;
183        realPos.w = 1.0f;
184
185
186        ///////////
187        //-- reprojection from new frame into old one
188
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
199        float oldWeight = clamp(oldCol.z, 0, temporalCoherence);
200        float oldNumSamples = oldCol.y;
201
202        float newWeight;
203
204        float newNumSamples = ao.y;
205
206        if (//(temporalCoherence > 0) &&
207                (tex.x >= 0.0f) && (tex.x < 1.0f) &&
208                (tex.y >= 0.0f) && (tex.y < 1.0f) &&
209                (abs(depthDif) < 1e-4f)
210                // if visibility changed in the surrounding area we have to recompute
211                && (oldNumSamples > 0.8f * newNumSamples)
212                //&& (oldAvgDepth / newAvgDepth > 0.99)
213                )
214        {
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;
220        }
221        else
222        {       
223                OUT.illum_col.xy = ao.xy;
224                newWeight = 0;
225        }
226
227        OUT.illum_col.z = newWeight;
228        OUT.illum_col.w = currentDepth;
229
230        return OUT;
231}
232
233
234pixel combine(fragment IN,
235                          uniform sampler2D colors,
236                          uniform sampler2D ssaoTex,
237                          uniform sampler2D positions)
238{
239        pixel OUT;
240
241        float4 col = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0));
242        float4 ao = tex2D(ssaoTex, IN.texCoord.xy);
243
244        OUT.illum_col = col * ao.x;
245        //OUT.illum_col = float4(ao.x,ao.x,ao.x, ao.w);
246        OUT.illum_col.w = col.w;
247
248        return OUT;
249}
Note: See TracBrowser for help on using the repository browser.