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

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

made ssao parameters more flexible
started to implement lense flare

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