source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/combineSsaoSep.cg @ 3317

Revision 3317, 7.5 KB checked in by mattausch, 15 years ago (diff)
Line 
1#include "../shaderenv.h"
2#include "common.h"
3
4
5/*************************************************/
6/*     Filter for combining ssao with image      */
7/*************************************************/
8
9
10struct fragment
11{
12        float2 texCoord: TEXCOORD0;
13        float3 view: TEXCOORD1;
14};
15
16
17struct pixel
18{
19        float4 illum_col: COLOR0;
20};
21
22
23float ComputeConvergenceHalfRes(uniform sampler2D ssaoTex,
24                                                                float2 texCoord,
25                                                                float2 halfres)
26{
27    // the following has to be done for half resolution ssao:
28        // get the minimum convergence by exactly sampling the 4 surrounding
29        // texels in the old texture, otherwise flickering because convergence
30        // will be interpolated when upsampling and filter size does not match!
31
32        float4 texelCenterConv;
33        const float xoffs = .5f / halfres.x; const float yoffs = .5f / halfres.y;
34
35        // get position exactly between old texel centers
36        float2 center;
37        center.x = (floor(texCoord.x * halfres.x - .5f) + 1.0f) / halfres.x;
38        center.y = (floor(texCoord.y * halfres.y - .5f) + 1.0f) / halfres.y;
39
40        texelCenterConv.x = tex2Dlod(ssaoTex, float4(center + float2( xoffs,  yoffs), 0, 0)).y;
41        texelCenterConv.y = tex2Dlod(ssaoTex, float4(center + float2( xoffs, -yoffs), 0, 0)).y;
42        texelCenterConv.z = tex2Dlod(ssaoTex, float4(center + float2(-xoffs, -yoffs), 0, 0)).y;
43        texelCenterConv.w = tex2Dlod(ssaoTex, float4(center + float2(-xoffs,  yoffs), 0, 0)).y;
44
45        const float m1 = min(texelCenterConv.x, texelCenterConv.y);
46        const float m2 = min(texelCenterConv.z, texelCenterConv.w);
47
48        const float minConvergence = min(m1, m2);
49        return minConvergence;
50}
51
52
53float2 FilterSample(float4 sampleTexCoord,
54                                        uniform sampler2D ssaoTex,
55                                        uniform sampler2D colorsTex,
56                                        float3 centerPos,
57                                        float3 bl,
58                                        float3 br,
59                                        float3 tl,
60                                        float3 tr,
61                                        float maxConvergence)
62{
63        float2 aoSample = tex2Dlod(ssaoTex, sampleTexCoord);
64               
65        // check spatial discontinuity
66        // note: using the depth from the color texture is not 100% correct as depth was
67        // not scaled with the interpolated view vector depth yet ...
68        float3 samplePos = ReconstructSamplePos(colorsTex, sampleTexCoord.xy, bl, br, tl, tr);
69        //samplePos = ReconstructSamplePos(ssaoTex, sampleTexCoord.xy, bl, br, tl, tr);
70
71        //float len = min(SqrLen(centerPos - samplePos), 1e2f);
72        float len = distance(centerPos, samplePos);
73        float spatialFactor = 1.0f / max(len, 1e-3f);
74
75        float convergenceFactor = min(aoSample.y + 1.0f, maxConvergence);
76        convergenceFactor *= convergenceFactor;
77
78        // combine the weights
79        float w = convergenceFactor * spatialFactor;
80        //float w = spatialFactor;
81        float average = aoSample.x * w;
82
83        return float2(average, w);
84}
85
86
87/** Filter taking into account depth, normal discontinuities
88   and ssao convergence of a sample (the higher the more reliably
89   has the sample a correct ssao value)
90*/
91float FilterXY(float2 texCoord,
92                           uniform sampler2D ssaoTex,
93                           uniform sampler2D colorsTex,
94                           float3 bl,
95                           float3 br,
96                           float3 tl,
97                           float3 tr,
98                           float2 xyStep,
99                           float convergence,
100                           float maxConvergence
101                           )
102{
103        float2 result = float2(0.0f, 0.0f);
104       
105        const float3 centerPos = ReconstructSamplePos(colorsTex, texCoord, bl, br, tl, tr);
106
107        const float scale = saturate((SSAO_CONVERGENCE_THRESHOLD - convergence) / SSAO_CONVERGENCE_THRESHOLD);
108        //const int radius = SSAO_FILTER_RADIUS * saturate((SSAO_CONVERGENCE_THRESHOLD - convergence) / SSAO_CONVERGENCE_THRESHOLD);
109       
110        //for (int i = -radius; i <= radius; ++ i)
111        for (int i = -SSAO_FILTER_RADIUS; i <= SSAO_FILTER_RADIUS; ++ i)
112        {
113                float4 sampleTexCoord = float4(texCoord + i * xyStep * scale, .0f, .0f);
114                result += FilterSample(sampleTexCoord, ssaoTex, colorsTex, centerPos, bl, br, tl, tr, maxConvergence);
115        }
116
117        result.x /= max(result.y, 1e-6f);
118
119        return saturate(result.x);
120}
121
122
123/** In between step that only filters in one direction
124*/
125pixel FilterSsaoHalfRes(fragment IN,
126                                                uniform sampler2D colorsTex,
127                                                uniform sampler2D ssaoTex,
128                                                uniform float3 bl,
129                                                uniform float3 br,
130                                                uniform float3 tl,
131                                                uniform float3 tr,
132                                                uniform float2 res
133                                                 )
134{
135        pixel OUT;
136
137        const float depth = tex2Dlod(colorsTex, float4(IN.texCoord, 0, 0)).w;
138
139        OUT.illum_col = tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0));
140        // compute minimal convergence for savetly reasons, write it out
141        const float convergence = ComputeConvergenceHalfRes(ssaoTex, IN.texCoord, res * 0.5f);
142        OUT.illum_col.y = convergence;
143
144        const float2 xyStep = float2(1.0f / res.x, 0);
145
146        // filter reaches size 1 pixel when sample size reaches threshold
147        // afterwards we do not use the filter anymore
148
149        // filter up to a certain convergance value and leave out background (sky) by checking depth
150        if ((convergence < SSAO_CONVERGENCE_THRESHOLD) && (depth < DEPTH_THRESHOLD))
151        {
152                // the filtered ssao value
153                OUT.illum_col.x = FilterXY(IN.texCoord, ssaoTex, colorsTex, bl, br, tl, tr, xyStep, convergence, maxConvergence);
154        }
155
156        return OUT;
157}
158
159/** In between step that only filters in one direction
160*/
161pixel FilterSsaoFullRes(fragment IN,
162                                                uniform sampler2D colorsTex,
163                                                uniform sampler2D ssaoTex,
164                                                uniform float3 bl,
165                                                uniform float3 br,
166                                                uniform float3 tl,
167                                                uniform float3 tr,
168                                                uniform float2 res,
169                                                uniform float maxConvergence
170                                                )
171{
172        pixel OUT;
173
174        const float depth = tex2Dlod(colorsTex, float4(IN.texCoord, 0, 0)).w;
175
176        OUT.illum_col = tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0));
177        // just take unfiltered convergence in current pixel
178        const float convergence = OUT.illum_col.y;
179
180        // filter reaches size 1 pixel when sample size reaches threshold
181        // afterwards we do not use the filter anymore
182
183        float2 xyStep = float2(1.0f / res.x, 0);
184
185        // filter up to a certain convergance value and leave out background (sky) by checking depth
186        if ((convergence < SSAO_CONVERGENCE_THRESHOLD) && (depth < DEPTH_THRESHOLD))
187        {
188                // the filtered ssao value
189                OUT.illum_col.x = FilterXY(IN.texCoord, ssaoTex, colorsTex, bl, br, tl, tr, xyStep, convergence, maxConvergence);
190        }
191
192        return OUT;
193}
194
195
196/** Function combining image and indirect illumination buffer using a
197    depth and convergence aware discontinuity filter.
198*/
199pixel CombineSsao(fragment IN,
200                                  uniform sampler2D colorsTex,
201                                  uniform sampler2D ssaoTex,
202                                  uniform float3 bl,
203                                  uniform float3 br,
204                                  uniform float3 tl,
205                                  uniform float3 tr,
206                                  uniform float2 res,
207                                  uniform float maxConvergence
208                                  )
209{
210        pixel OUT;
211
212        float4 col = tex2Dlod(colorsTex, float4(IN.texCoord, 0, 0));
213        float4 ao = tex2Dlod(ssaoTex, float4(IN.texCoord, 0, 0));
214
215        const float depth = col.w;
216        // just take unfiltered convergence in current pixel
217        const float convergence = ao.y;
218
219        const float2 xyStep = float2(0, 1.0f / res.y);
220       
221        // filter reaches size 1 pixel when sample size reaches threshold
222        // afterwards we do not use the filter anymore
223
224        // filter up to a certain convergance value and leave out background (sky) by checking depth
225        if ((convergence < SSAO_CONVERGENCE_THRESHOLD) && (depth < DEPTH_THRESHOLD))
226        {
227                // the filtered ssao value
228                ao.x = FilterXY(IN.texCoord, ssaoTex, colorsTex, bl, br, tl, tr, xyStep, convergence, maxConvergence);
229        }
230
231        // just apply ssao if we are not in the sky
232        if (depth < DEPTH_THRESHOLD)
233        {
234                OUT.illum_col.xyz = col.xyz * max(1e-3f, 1.0f - ao.x);
235                //OUT.illum_col.xyz = max(1e-3f, 1.0f - ao.x);
236        }
237        else
238        {
239                OUT.illum_col.xyz = col.xyz;
240        }
241
242        OUT.illum_col.w = col.w;
243
244        return OUT;
245}
Note: See TracBrowser for help on using the repository browser.