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

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

updated shader programs

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