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

Revision 2991, 7.1 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////////////////////
2// SSAO + color bleeding shader
3// based on shader of Alexander Kusternig
4
5#include "../shaderenv.h"
6
7
8struct fragment
9{
10         // normalized screen position
11        float4 pos: WPOS;
12        float4 texCoord: TEXCOORD0;
13        float3 view: COLOR0;
14};
15
16
17struct pixel2
18{
19        float4 ssao_col: COLOR0;
20        float4 illum_col: COLOR1;
21};
22
23
24struct pixel
25{
26        float4 illum_col: COLOR0;
27};
28
29
30float2 myreflect(float2 pt, float2 n)
31{
32        // distance to plane
33        float d = dot(n, pt);
34        // reflect around plane
35        float2 rpt = pt - d * 2.0f * n;
36        return rpt;
37}
38
39struct GiStruct
40{
41        float3 illum;
42        float2 ao;
43};
44
45
46
47inline float3 Interpol(float2 w, float3 bl, float3 br, float3 tl, float3 tr)
48{
49        float3 x1 = lerp(bl, tl, w.y);
50        float3 x2 = lerp(br, tr, w.y);
51        float3 v = lerp(x1, x2, w.x);
52
53        return v;
54}
55
56
57/** Computes  diffuse reflections + ambient occlusion
58*/
59GiStruct globIllum(fragment IN,
60                                   uniform sampler2D colors,
61                                   uniform sampler2D positions,
62                                   uniform sampler2D noiseTexture,
63                                   uniform float2 samples[NUM_SAMPLES],
64                                   uniform float3 currentNormal,
65                                   uniform float4 centerPosition,
66                                   float w,
67                                   // uniform float3 viewDir,
68                                   uniform float3 eyePos,
69                                   uniform float3 bl,
70                                   uniform float3 br,
71                                   uniform float3 tl,
72                                   uniform float3 tr
73                                   )
74{
75        GiStruct gi;
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        // ao is in stored in the w component
82        float3 total_color = float3(0, 0, 0);
83        float total_ao = 0.0f;
84        float numSamples = 0.0f;
85
86        ////////////
87        //-- the main sampling loop
88
89        for (int i = 0; i < NUM_SAMPLES; i ++)
90        {
91                float2 offset = samples[i];
92
93#if 1
94                ////////////////////
95                // add random noise: reflect around random normal vector (warning: slow!)
96                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy;
97                float2 offsetTransformed = myreflect(offset, mynoise);
98#else
99                float2 offsetTransformed = offset;
100#endif
101                // weight with projected coordinate to reach similar kernel size for near and far
102                float2 texcoord = IN.texCoord.xy + offsetTransformed * AREA_SIZE * w;
103
104                if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f))
105                        ++ numSamples;
106
107                // reconstruct world space position from sample
108                float4 sample = tex2Dlod(colors, float4(texcoord, 0, SSAO_MIPMAP_LEVEL));
109                const float eyeSpaceDepth = sample.w;
110                float3 rotView = normalize(Interpol(texcoord, bl, br, tl, tr));
111               
112                const float3 sample_position = eyePos - rotView * eyeSpaceDepth;
113                const float3 sample_color = sample.xyz;
114
115                // use lower lod level to improve cache coherence
116                //float3 sample_position = tex2Dlod(positions, float4(texcoord, 0, SSAO_MIPMAP_LEVEL)).xyz;
117                //float3 sample_color = tex2Dlod(colors, float4(texcoord, 0, GI_MIPMAP_LEVEL)).xyz;
118
119                float3 vector_to_sample = sample_position - centerPosition.xyz;
120                const float length_to_sample = length(vector_to_sample);
121
122                float3 direction_to_sample = vector_to_sample / length_to_sample;
123
124                // Angle between current normal and direction to sample controls AO intensity.
125                float cos_angle = max(dot(direction_to_sample, currentNormal), 0);
126
127                // distance between current position and sample position controls AO intensity.
128                const float distance_intensity =
129                        (SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample);
130
131                // if normal perpenticular to view dir, only half of the samples count
132#if 0
133                const float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal));
134                total_color.w -= cos_angle * distance_intensity * view_correction;
135                total_color.xyz += cos_angle * distance_intensity * view_correction * sample_color * ILLUM_INTENSITY;
136#endif
137                total_ao += cos_angle * distance_intensity;
138                total_color += cos_angle * distance_intensity * sample_color * ILLUM_INTENSITY;
139        }
140
141        gi.illum = total_color;
142        gi.ao = float2(max(0.0f, 1.0f - total_ao), numSamples);
143
144        //return saturate(total_color);
145        return gi;
146}
147
148
149/** The mrt shader for screen space ambient occlusion + indirect illumination
150*/
151pixel2 main(fragment IN,
152                   uniform sampler2D colors,
153                   uniform sampler2D positions,
154                   uniform sampler2D normals,
155                   uniform sampler2D noiseTexture,
156                   uniform float2 samples[NUM_SAMPLES],
157                   uniform sampler2D oldSsaoTex,
158                   uniform sampler2D oldIllumTex,
159                   const uniform float4x4 oldModelViewProj,
160                   uniform float maxDepth,
161                   uniform float temporalCoherence,
162                   uniform float3 eyePos,
163                   uniform float3 bl,
164                   uniform float3 br,
165                   uniform float3 tl,
166                   uniform float3 tr
167                   )
168{
169        pixel2 OUT;
170
171        float4 norm = tex2D(normals, IN.texCoord.xy);
172        float3 normal = normalize(norm.xyz);   
173        // something like a constant ambient term
174        const float amb = norm.w;
175       
176        /// the current view direction
177        //float3 viewDir = normalize(IN.view);
178
179        // the w coordinate from the persp. projection
180        float w = norm.w;
181        // the current world position
182        const float4 centerPosition = tex2D(positions, IN.texCoord.xy);
183        // the current color
184        const float4 currentCol = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0));
185        // the current depth is stored in the w component
186        const float currentDepth = centerPosition.w;
187
188        GiStruct gi = globIllum(IN, colors, positions, noiseTexture, samples, normal, centerPosition, w, eyePos, bl, br, tl, tr);
189       
190
191        /////////////////
192        //-- compute temporally smoothing
193
194        float4 realPos = centerPosition * maxDepth;
195        realPos.w = 1.0f;
196
197        float4 oldPos = mul(oldModelViewProj, realPos);
198
199        const float newDepth = oldPos.z / oldPos.w;
200
201        float2 tex = (oldPos.xy / oldPos.w) * 0.5f + 0.5f;
202
203        float4 oldSsao = tex2D(oldSsaoTex, tex);
204        float4 oldIllum = tex2D(oldIllumTex, tex);
205
206        const float oldDepth = oldSsao.w;
207        const float depthDif = 1.0f - newDepth / oldDepth;
208
209        float oldWeight = clamp(oldSsao.z, 0, temporalCoherence);
210        float newWeight;
211
212        const float oldNumSamples = oldSsao.y;
213        const float oldAvgDepth = oldSsao.z;
214
215        if ((temporalCoherence > 0.0f) &&
216                (tex.x >= 0.0f) && (tex.x < 1.0f) &&
217                (tex.y >= 0.0f) && (tex.y < 1.0f) &&
218                (abs(depthDif) < 1e-3f)
219                // check if something changed in the surrounding area
220                && (oldNumSamples > 0.2 * gi.ao.y)
221                //&& (oldAvgDepth / newAvgDepth > 0.99)
222                )
223        {
224                newWeight = oldWeight + 1;
225
226                OUT.ssao_col.xy = (gi.ao + oldSsao.xy * oldWeight) / newWeight;
227                OUT.illum_col.xyz  = (gi.illum + oldIllum.xyz * oldWeight) / newWeight;
228        }
229        else
230        {
231                newWeight = 0;
232
233                OUT.ssao_col.xy = gi.ao.xy;
234                OUT.illum_col.xyz = gi.illum;
235        }
236
237        OUT.ssao_col.z = newWeight;
238        OUT.ssao_col.w = currentDepth;
239
240        return OUT;
241}
242
243
244pixel combine(fragment IN,
245                          uniform sampler2D colors,
246                          uniform sampler2D ssaoTex,
247                          uniform sampler2D illumTex
248                          )
249{
250        pixel OUT;
251
252        float4 col = tex2D(colors, IN.texCoord.xy);
253        float ao = tex2D(ssaoTex, IN.texCoord.xy).x;
254        float4 illum = tex2D(illumTex, IN.texCoord.xy);
255       
256        OUT.illum_col = (col + illum) * ao;
257        OUT.illum_col.w = col.w;
258
259        return OUT;
260}
Note: See TracBrowser for help on using the repository browser.