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

Revision 3332, 7.0 KB checked in by mattausch, 16 years ago (diff)

debug / performance stuff

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        float2 texCoord: TEXCOORD0;
11        float3 view: TEXCOORD1;
12};
13
14
15struct pixel2
16{
17        float4 ssao_col: COLOR0;
18        float4 illum_col: COLOR1;
19};
20
21
22struct pixel
23{
24        float4 illum_col: COLOR0;
25};
26
27
28float2 myreflect(float2 pt, float2 n)
29{
30        // distance to plane
31        float d = dot(n, pt);
32        // reflect around plane
33        float2 rpt = pt - d * 2.0f * n;
34        return rpt;
35}
36
37
38struct GiStruct
39{
40        float3 illum;
41        float2 ao;
42};
43
44
45
46inline float3 Interpol(float2 w, float3 bl, float3 br, float3 tl, float3 tr)
47{
48        float3 x1 = lerp(bl, tl, w.y);
49        float3 x2 = lerp(br, tr, w.y);
50        float3 v = lerp(x1, x2, w.x);
51
52        return v;
53}
54
55
56/** Computes  diffuse reflections + ambient occlusion
57*/
58GiStruct globIllum(fragment IN,
59                                   uniform sampler2D colors,
60                                   uniform sampler2D noiseTexture,
61                                   uniform float2 samples[NUM_SAMPLES],
62                                   uniform float3 currentNormal,
63                                   uniform float3 centerPosition,
64                                   float scaleFactor,
65                                   uniform float3 bl,
66                                   uniform float3 br,
67                                   uniform float3 tl,
68                                   uniform float3 tr,
69                                   float3 viewDir,
70                                   float sampleIntensity
71                                   )
72{
73        GiStruct gi;
74
75        // Check in a circular area around the current position.
76        // Shoot vectors to the positions there, and check the angle to these positions.
77        // Summing up these angles gives an estimation of the occlusion at the current position.
78
79        // ao is in stored in the w component
80        float3 total_color = float3(0, 0, 0);
81        float total_ao = 0.0f;
82        float numSamples = 0.0f;
83
84        ////////////
85        //-- the main sampling loop
86
87        for (int i = 0; i < NUM_SAMPLES; i ++)
88        {
89                const float2 offset = samples[i];
90
91#if 1
92                ////////////////////
93                // add random noiseTex: reflect around random normal vector (warning: slow!)
94                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy;
95                float2 offsetTransformed = myreflect(offset, mynoise);
96#else
97                float2 offsetTransformed = offset;
98#endif
99                // weight with projected coordinate to reach similar kernel size for near and far
100                float2 texcoord = IN.texCoord.xy + offsetTransformed * scaleFactor;
101
102                //if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f)) ++ numSamples;
103
104
105                //////////
106                //-- reconstruct world space position from sample
107
108                const float4 sample = tex2Dlod(colors, float4(texcoord, 0, 0));
109                //const float4 sample = tex2D(colors, texcoord);
110
111                const float eyeSpaceDepth = sample.w;
112                float3 rotView = Interpol(texcoord, bl, br, tl, tr);
113               
114                const float3 samplePos = - rotView * eyeSpaceDepth;
115                const float3 sampleCol = sample.xyz;
116
117                // distance between current position and sample position controls AO intensity.
118
119                float3 dirSample = samplePos - centerPosition.xyz;
120                const float magSample = length(dirSample);
121                // normalize
122                dirSample /= magSample;
123
124                // use angle between current normal and direction to sample controls AO intensity.
125                float cosAngle = max(dot(dirSample, currentNormal), 0);
126
127                const float denom = (DISTANCE_SCALE + magSample * magSample);
128
129                float2 intensity = float2(sampleIntensity, ILLUM_INTENSITY);
130                intensity /= denom;
131
132                // if normal perpenticular to view dir, only the samples approx count half
133#if 1
134                const float viewCorrect = 1.0f + VIEW_CORRECTION_SCALE * dot(viewDir, currentNormal);
135       
136                total_ao += cosAngle * intensity.x * viewCorrect;
137                total_color += cosAngle * intensity.y * sampleCol * viewCorrect;
138#else
139                total_ao += cos_angle * intensity.x;
140                total_color += cos_angle * intensity.y * sampleCol;
141#endif
142        }
143
144        gi.illum = total_color;
145        gi.ao = float2(max(0.0f, 1.0f - total_ao), numSamples);
146
147        return gi;
148}
149
150
151
152pixel2 main(fragment IN,
153                   uniform sampler2D colors,
154                   uniform sampler2D normals,
155                   uniform sampler2D noiseTex,
156                   uniform float2 samples[NUM_SAMPLES],
157                   uniform sampler2D oldSsaoTex,
158                   uniform sampler2D oldIllumTex,
159                   const uniform float4x4 oldModelViewProj,
160                   const uniform float4x4 modelViewProj,
161                   uniform float temporalCoherence,
162                   uniform float3 bl,
163                   uniform float3 br,
164                   uniform float3 tl,
165                   uniform float3 tr,
166                   uniform float kernelRadius,
167                   uniform float sampleIntensity
168                   )
169{
170        pixel2 OUT;
171
172        const float3 normal = tex2Dlod(normals, float4(IN.texCoord, 0 ,0)).xyz;
173
174       
175        /////////////
176        //-- reconstruct position from the eye space depth
177
178        float3 viewDir = IN.view;
179        const float eyeDepth = tex2Dlod(colors, float4(IN.texCoord, 0, 0)).w;
180       
181        const float4 eyeSpacePos = float4(-viewDir * eyeDepth, 1.0f);
182
183        // calculcate the current projected depth for next frame
184        float4 currentPos = mul(modelViewProj, eyeSpacePos);
185
186        const float w = kernelRadius / currentPos.w;
187        currentPos /= currentPos.w;
188       
189        const float currentDepth = currentPos.z;
190
191        ///////////
192        //-- compute color bleeding + ao
193
194        GiStruct gi = globIllum(IN, colors, noiseTex, samples, normal, eyeSpacePos,
195                                    w, bl, br, tl, tr, normalize(IN.view), sampleIntensity);
196       
197
198        /////////////////
199        //-- compute temporally smoothing
200
201        // reprojection new frame into old one
202        // calculate projected depth
203        float4 projPos = mul(oldModelViewProj, eyeSpacePos);
204        projPos /= projPos.w;
205
206        // the current depth projected into the old frame
207        const float projDepth = projPos.z;
208
209        // fit from unit cube into 0 .. 1
210        float2 tex = projPos.xy * 0.5f + 0.5f;
211
212        // retrieve the sample from the last frame
213        float3 oldSsao = tex2D(oldSsaoTex, tex).xyz;
214        float3 oldIllum = tex2D(oldIllumTex, tex).xyz;
215
216        const float oldDepth = oldSsao.z;
217        //const float depthDif = 1.0f - projDepth / oldDepth;
218        const float depthDif = projDepth - oldDepth;
219
220        // the weights that indicate the state of convergence
221        const float oldWeight = clamp(oldSsao.y, .0f, temporalCoherence);
222        float newWeight;
223
224        //const float oldNumSamples = oldSsao.y;
225       
226        if ((temporalCoherence > 1e-6f) &&
227                (tex.x >= 0.0f) && (tex.x < 1.0f) &&
228                (tex.y >= 0.0f) && (tex.y < 1.0f) &&
229                (abs(depthDif) < MIN_DEPTH_DIFF)
230                // check if something changed in the surrounding area
231                //&& (oldNumSamples > 0.2 * gi.ao.y)
232                )
233        {
234                newWeight = oldWeight + 1;
235
236                float4 tmp = float4(gi.ao.x, gi.illum);
237                float4 oldTmp = float4(oldSsao.x, oldIllum);
238
239                float4 interpol = (tmp + oldTmp * oldWeight) / newWeight;
240
241                OUT.ssao_col.x = interpol.x;
242                OUT.illum_col.xyz = interpol.yzw;
243        }
244        else
245        {
246                newWeight = 0;
247
248                OUT.ssao_col.x = gi.ao.x;
249                OUT.illum_col.xyz = gi.illum;
250        }
251
252        OUT.ssao_col.y = newWeight;
253        OUT.ssao_col.z = currentDepth;
254
255        return OUT;
256}
257
258
259pixel combine(fragment IN,
260                          uniform sampler2D colorsTex,
261                          uniform sampler2D ssaoTex,
262                          uniform sampler2D illumTex
263                          )
264{
265        pixel OUT;
266
267        float4 col = tex2Dlod(colorsTex, float4(IN.texCoord, 0, 0));
268        float ao = tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0)).x;
269
270        float3 illum = tex2Dlod(illumTex, float4(IN.texCoord, 0, 0)).xyz;
271
272        OUT.illum_col.xyz = (col.xyz + illum) * ao;
273        //OUT.illum_col.xyz = col.xyz * ao;
274
275        OUT.illum_col.w = col.w;
276
277        return OUT;
278}
Note: See TracBrowser for help on using the repository browser.