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

Revision 3010, 7.2 KB checked in by mattausch, 16 years ago (diff)
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: TEXCOORD1;
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 noiseTexture,
62                                   uniform float2 samples[NUM_SAMPLES],
63                                   uniform float3 currentNormal,
64                                   uniform float3 centerPosition,
65                                   float w,
66                                   uniform float3 eyePos,
67                                   uniform float3 bl,
68                                   uniform float3 br,
69                                   uniform float3 tl,
70                                   uniform float3 tr
71                                   //, uniform float3 viewDir
72                                   )
73{
74        GiStruct gi;
75
76        // Check in a circular area around the current position.
77        // Shoot vectors to the positions there, and check the angle to these positions.
78        // Summing up these angles gives an estimation of the occlusion at the current position.
79
80        // ao is in stored in the w component
81        float3 total_color = float3(0, 0, 0);
82        float total_ao = 0.0f;
83        float numSamples = 0.0f;
84
85        ////////////
86        //-- the main sampling loop
87
88        for (int i = 0; i < NUM_SAMPLES; i ++)
89        {
90                float2 offset = samples[i];
91
92#if 1
93                ////////////////////
94                // add random noise: reflect around random normal vector (warning: slow!)
95                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy;
96                float2 offsetTransformed = myreflect(offset, mynoise);
97#else
98                float2 offsetTransformed = offset;
99#endif
100                // weight with projected coordinate to reach similar kernel size for near and far
101                float2 texcoord = IN.texCoord.xy + offsetTransformed * AREA_SIZE * w;
102
103                //if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f)) ++ numSamples;
104
105
106                //////////
107                //-- reconstruct world space position from sample
108
109                float4 sample = tex2Dlod(colors, float4(texcoord, 0, 0));
110                const float eyeSpaceDepth = sample.w;
111                //float3 rotView = normalize(Interpol(texcoord, bl, br, tl, tr));
112                float3 rotView = Interpol(texcoord, bl, br, tl, tr);
113               
114               
115                const float3 sample_position = eyePos - rotView * eyeSpaceDepth;
116                const float3 sample_color = sample.xyz;
117
118                float3 vector_to_sample = sample_position - centerPosition.xyz;
119                const float length_to_sample = length(vector_to_sample);
120
121                float3 direction_to_sample = vector_to_sample / length_to_sample;
122
123                // use angle between current normal and direction to sample controls AO intensity.
124                float cos_angle = max(dot(direction_to_sample, currentNormal), 0);
125
126                // distance between current position and sample position controls AO intensity.
127                const float distance_intensity =
128                        (SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample);
129
130                // if normal perpenticular to view dir, only half of the samples count
131#if 0
132                const float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal));
133                total_color.w -= cos_angle * distance_intensity * view_correction;
134                total_color.xyz += cos_angle * distance_intensity * view_correction * sample_color * ILLUM_INTENSITY;
135#endif
136                total_ao += cos_angle * distance_intensity;
137                total_color += cos_angle * distance_intensity * sample_color * ILLUM_INTENSITY;
138        }
139
140        gi.illum = total_color;
141        gi.ao = float2(max(0.0f, 1.0f - total_ao), numSamples);
142
143        //return saturate(total_color);
144        return gi;
145}
146
147
148
149pixel2 main(fragment IN,
150                   uniform sampler2D colors,
151                   uniform sampler2D positions,
152                   uniform sampler2D normals,
153                   uniform sampler2D noiseTexture,
154                   uniform float2 samples[NUM_SAMPLES],
155                   uniform sampler2D oldSsaoTex,
156                   uniform sampler2D oldIllumTex,
157                   const uniform float4x4 oldModelViewProj,
158                   const uniform float4x4 modelViewProj,
159                   uniform float maxDepth,
160                   uniform float temporalCoherence,
161                   uniform float3 eyePos,
162                   uniform float3 bl,
163                   uniform float3 br,
164                   uniform float3 tl,
165                   uniform float3 tr
166                   )
167{
168        pixel2 OUT;
169
170        float4 norm = tex2D(normals, IN.texCoord.xy);
171        float3 normal = normalize(norm.xyz);   
172
173        // the w coordinate from the persp. projection
174        float w = norm.w;
175
176
177        /////////////
178        //-- reconstruct position from the eye space depth
179
180        float3 viewDir = IN.view;
181        const float eyeDepth = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0)).w;
182       
183        float3 centerPosition;
184        centerPosition.xyz = eyePos - viewDir * eyeDepth;
185       
186        //const float3 centerPosition = tex2D(positions, IN.texCoord.xy).xyz;
187
188
189        ///////////
190        //-- compute color bleeding + ao
191
192        GiStruct gi = globIllum(IN, colors, noiseTexture, samples, normal, centerPosition, w, eyePos, bl, br, tl, tr);
193       
194
195        /////////////////
196        //-- compute temporally smoothing
197
198        float4 realPos = float4(centerPosition * maxDepth, 1.0f);
199
200
201        // calculcate the current projected depth for next frame
202        float4 currentPos = mul(modelViewProj, realPos);
203        currentPos /= currentPos.w;
204        const float currentDepth = currentPos.z;
205       
206
207        ///////////
208        //-- reprojection new frame into old one
209       
210        // calculate projected depth
211        float4 projPos = mul(oldModelViewProj, realPos);
212        projPos /= projPos.w;
213
214        // the current depth projected into the old frame
215        const float projDepth = projPos.z;
216
217        // fit from unit cube into 0 .. 1
218        float2 tex = (projPos.xy) * 0.5f + 0.5f;
219
220        // retrieve the sample from the last frame
221        float4 oldSsao = tex2D(oldSsaoTex, tex);
222        float4 oldIllum = tex2D(oldIllumTex, tex);
223
224        const float oldDepth = oldSsao.w;
225        const float depthDif = 1.0f - projDepth / oldDepth;
226
227        float oldWeight = clamp(oldSsao.z, 0, temporalCoherence);
228
229        float newWeight;
230
231        //const float oldNumSamples = oldSsao.y;
232        //const float oldAvgDepth = oldSsao.z;
233
234        if (//(temporalCoherence > 0.0f) &&
235                (tex.x >= 0.0f) && (tex.x < 1.0f) &&
236                (tex.y >= 0.0f) && (tex.y < 1.0f) &&
237                (abs(depthDif) < MIN_DEPTH_DIFF)
238                // check if something changed in the surrounding area
239                //&& (oldNumSamples > 0.2 * gi.ao.y)
240                )
241        {
242                newWeight = oldWeight + 1;
243
244                OUT.ssao_col.xy = (gi.ao + oldSsao.xy * oldWeight) / newWeight;
245                OUT.illum_col.xyz  = (gi.illum + oldIllum.xyz * oldWeight) / newWeight;
246        }
247        else
248        {
249                newWeight = 0;
250
251                OUT.ssao_col.xy = gi.ao.xy;
252                OUT.illum_col.xyz = gi.illum;
253        }
254
255        OUT.ssao_col.z = newWeight;
256        OUT.ssao_col.w = currentDepth;
257
258        return OUT;
259}
260
261
262pixel combine(fragment IN,
263                          uniform sampler2D colors,
264                          uniform sampler2D ssaoTex,
265                          uniform sampler2D illumTex
266                          )
267{
268        pixel OUT;
269
270        float4 col = tex2D(colors, IN.texCoord.xy);
271        float ao = tex2D(ssaoTex, IN.texCoord.xy).x;
272        float4 illum = tex2D(illumTex, IN.texCoord.xy);
273       
274        OUT.illum_col = (col + illum) * ao;
275        OUT.illum_col.w = col.w;
276
277        return OUT;
278}
Note: See TracBrowser for help on using the repository browser.