History

A working prototype of ao...

samcake committed 10 years ago

Commit 2486d941 parent f4b4b6212 files · +142 −134Browse files

Unified · Split

12 files
  1. examples/utilities/tools/renderEngineDebug.js +1 −1
  2. libraries/render-utils/src/AmbientOcclusionEffect.cpp +11 −81
  3. libraries/render-utils/src/AmbientOcclusionEffect.h +1 −0
  4. libraries/render-utils/src/DeferredBuffer.slh +11 −3
  5. libraries/render-utils/src/FramebufferCache.cpp +1 −1
  6. libraries/render-utils/src/directional_ambient_light.slf +2 −2
  7. libraries/render-utils/src/directional_light.slf +2 −2
  8. libraries/render-utils/src/directional_skybox_light.slf +2 −2
  9. libraries/render-utils/src/ssao.slh +93 −2
  10. libraries/render-utils/src/ssao_makeHorizontalBlur.slf +4 −4
  11. libraries/render-utils/src/ssao_makeOcclusion.slf +10 −31
  12. libraries/render-utils/src/ssao_makeVerticalBlur.slf +4 −5
examples/utilities/tools/renderEngineDebug.js+1−1
@@ -52,7 +52,7 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", Render.overlay3D); · 51 unmodified lines
5252
5353 var resizing = false;
5454 var previousMode = Settings.getValue(SETTINGS_KEY, -1);
55−previousMode = 1;
55+previousMode = 4; // FIXME: just for debug purpose
5656 Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]);
5757 Render.deferredDebugMode = previousMode;
5858 Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 }; // Reset to default size
libraries/render-utils/src/AmbientOcclusionEffect.cpp+11−81
@@ -80,7 +80,8 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() { · 79 unmodified lines
8080 slotBindings.insert(gpu::Shader::Binding(std::string("ambientOcclusionParamsBuffer"), AmbientOcclusionEffect_ParamsSlot));
8181 slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), AmbientOcclusionEffect_DeferredTransformSlot));
8282 slotBindings.insert(gpu::Shader::Binding(std::string("pyramidMap"), AmbientOcclusionEffect_PyramidMapSlot));
83−
83+
84+ slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), AmbientOcclusionEffect_PyramidMapSlot + 1));
8485 gpu::Shader::makeProgram(*program, slotBindings);
8586
8687
@@ -90,7 +91,8 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() { · 3 unmodified lines
9091 state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
9192
9293 state->setColorWriteMask(true, true, true, false);
93−
94+ //state->setColorWriteMask(true, true, true, true);
95+
9496 // Good to go add the brand new pipeline
9597 _occlusionPipeline = gpu::Pipeline::create(program, state);
9698 }
@@ -147,83 +149,6 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getVBlurPipeline() { · 50 unmodified lines
147149
148150 // Good to go add the brand new pipeline
149151 _vBlurPipeline = gpu::Pipeline::create(program, state);
150−
151− const char blur_frag[] = R"SCRIBE(#version 410 core
152− //
153− // Created by Sam Gateau on 12/31/2015
154− // Copyright 2015 High Fidelity, Inc.
155− //
156− // Distributed under the Apache License, Version 2.0.
157− // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
158− //
159−
160− struct AmbientOcclusionParams {
161− vec4 _clipInfo;
162− mat4 _projection;
163− vec4 _radius_s0_s1_s2;
164− };
165−
166− uniform ambientOcclusionParamsBuffer {
167− AmbientOcclusionParams params;
168− };
169−
170− float evalZeyeFromZdb(float depth) {
171− return params._clipInfo.x / (depth * params._clipInfo.y + params._clipInfo.z);
172− }
173−
174− // the depth texture
175− uniform sampler2D depthMap;
176−
177− in vec2 varTexCoord0;
178− out vec4 outFragColor;
179−
180− ivec2 ssC = ivec2(gl_FragCoord.xy);
181−
182− vec4 temp = texelFetch(source, ssC, 0);
183−
184− keyPassThrough = temp.KEY_COMPONENTS;
185− float key = unpackKey(keyPassThrough);
186−
187− VALUE_TYPE sum = temp.VALUE_COMPONENTS;
188−
189− if (key == 1.0) {
190− // Sky pixel (if you aren't using depth keying, disable this test)
191− result = sum;
192− return;
193− }
194−
195− // Base weight for depth falloff. Increase this for more blurriness,
196− // decrease it for better edge discrimination
197− float BASE = gaussian[0];
198− float totalWeight = BASE;
199− sum *= totalWeight;
200−
201−
202− for (int r = -R; r <= R; ++r) {
203− // We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
204− // so the IF statement has no runtime cost
205− if (r != 0) {
206− temp = texelFetch(source, ssC + axis * (r * SCALE), 0);
207− float tapKey = unpackKey(temp.KEY_COMPONENTS);
208− VALUE_TYPE value = temp.VALUE_COMPONENTS;
209−
210− // spatial domain: offset gaussian tap
211− float weight = 0.3 + gaussian[abs(r)];
212−
213− // range domain (the "bilateral" weight). As depth difference increases, decrease weight.
214− weight *= max(0.0, 1.0
215− - (EDGE_SHARPNESS * 2000.0) * abs(tapKey - key)
216− );
217−
218− sum += value * weight;
219− totalWeight += weight;
220− }
221− }
222−
223− const float epsilon = 0.0001;
224− result = sum / (totalWeight + epsilon);
225−
226− )SCRIBE";
227152 }
228153 return _vBlurPipeline;
229154 }
@@ -346,6 +271,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext · 116 unmodified lines
346271 RenderArgs* args = renderContext->getArgs();
347272 auto framebufferCache = DependencyManager::get<FramebufferCache>();
348273 auto depthBuffer = framebufferCache->getPrimaryDepthTexture();
274+ auto normalBuffer = framebufferCache->getDeferredNormalTexture();
349275 auto pyramidFBO = framebufferCache->getDepthPyramidFramebuffer();
350276 auto occlusionFBO = framebufferCache->getOcclusionFramebuffer();
351277 auto occlusionBlurredFBO = framebufferCache->getOcclusionBlurredFramebuffer();
@@ -366,7 +292,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext · 14 unmodified lines
366292
367293 setClipInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip());
368294 _parametersBuffer.edit<Parameters>()._projection = monoProjMat;
369−
295+ _parametersBuffer.edit<Parameters>()._pixelInfo = args->_viewport;
370296
371297 auto pyramidPipeline = getPyramidPipeline();
372298 auto occlusionPipeline = getOcclusionPipeline();
@@ -404,9 +330,13 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext · 31 unmodified lines
404330
405331 // Occlusion pass
406332 batch.setPipeline(occlusionPipeline);
333+
334+ // batch.setFramebuffer(occlusionFinalFBO);
407335 batch.setResourceTexture(AmbientOcclusionEffect_PyramidMapSlot, pyramidFBO->getRenderBuffer(0));
336+ batch.setResourceTexture(AmbientOcclusionEffect_PyramidMapSlot + 1, normalBuffer);
408337 batch.draw(gpu::TRIANGLE_STRIP, 4);
409−
338+ batch.setResourceTexture(AmbientOcclusionEffect_PyramidMapSlot + 1, gpu::TexturePointer());
339+
410340 // Blur 1 pass
411341 batch.setFramebuffer(occlusionBlurredFBO);
412342 batch.setPipeline(firstHBlurPipeline);
libraries/render-utils/src/AmbientOcclusionEffect.h+1−0
@@ -34,6 +34,7 @@ private: · 33 unmodified lines
3434 // Class describing the uniform buffer with all the parameters common to the AO shaders
3535 class Parameters {
3636 public:
37+ glm::vec4 _pixelInfo;
3738 glm::vec4 _clipInfo;
3839 glm::mat4 _projection;
3940 glm::vec4 _radius_radius2_InvRadius6_s2{ 0.5, 0.5 * 0.5, 1.0 / (0.25 * 0.25 * 0.25), 0.0 };
libraries/render-utils/src/DeferredBuffer.slh+11−3
@@ -68,11 +68,14 @@ struct DeferredFragment { · 67 unmodified lines
6868 vec4 position;
6969 vec3 normal;
7070 vec3 diffuse;
71− float opacity;
71+ float obscurance;
7272 vec3 specular;
7373 float gloss;
74+ int mode;
7475 };
7576
77+const int LIGHT_MAPPED = 1;
78+
7679 DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) {
7780 DeferredFragment frag;
7881 frag.depthVal = texture(depthMap, texcoord).r;
@@ -88,11 +91,16 @@ DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec · 9 unmodified lines
8891 }
8992 frag.position = evalEyePositionFromZ(deferredTransform, frag.depthVal, texcoord);
9093
91− // Unpack the normal from the map
94+ // Unpack the normal from the map
9295 frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0));
96+
97+ frag.mode = 0;
98+ if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
99+ frag.mode = LIGHT_MAPPED;
100+ }
93101
94102 frag.diffuse = frag.diffuseVal.xyz;
95− frag.opacity = frag.normalVal.w;
103+ frag.obscurance = frag.diffuseVal.w;
96104 frag.specular = frag.specularVal.xyz;
97105 frag.gloss = frag.specularVal.w;
98106
libraries/render-utils/src/FramebufferCache.cpp+1−1
@@ -105,7 +105,7 @@ void FramebufferCache::createPrimaryFramebuffer() { · 104 unmodified lines
105105
106106
107107 // For AO:
108− _depthPyramidTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::HALF, gpu::RGB), width, height, smoothSampler));
108+ _depthPyramidTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), width, height, smoothSampler));
109109 _depthPyramidFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
110110 _depthPyramidFramebuffer->setRenderBuffer(0, _depthPyramidTexture);
111111 _depthPyramidFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
libraries/render-utils/src/directional_ambient_light.slf+2−2
@@ -27,7 +27,7 @@ void main(void) { · 26 unmodified lines
2727 DeferredTransform deferredTransform = getDeferredTransform();
2828 DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
2929
30− if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
30+ if (frag.mode == LIGHT_MAPPED) {
3131 vec3 color = evalLightmappedColor(
3232 deferredTransform.viewInverse,
3333 1.0,
@@ -38,7 +38,7 @@ void main(void) { · 4 unmodified lines
3838 } else {
3939 vec3 color = evalAmbienSphereGlobalColor(
4040 deferredTransform.viewInverse,
41− 1.0,
41+ frag.obscurance,
4242 frag.position.xyz,
4343 frag.normal,
4444 frag.diffuse,
libraries/render-utils/src/directional_light.slf+2−2
@@ -28,7 +28,7 @@ void main(void) { · 27 unmodified lines
2828 DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
2929
3030 // Light mapped or not ?
31− if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
31+ if (frag.mode == LIGHT_MAPPED) {
3232 vec3 color = evalLightmappedColor(
3333 deferredTransform.viewInverse,
3434 1.0,
@@ -39,7 +39,7 @@ void main(void) { · 4 unmodified lines
3939 } else {
4040 vec3 color = evalAmbienGlobalColor(
4141 deferredTransform.viewInverse,
42− 1.0,
42+ frag.obscurance,
4343 frag.position.xyz,
4444 frag.normal,
4545 frag.diffuse,
libraries/render-utils/src/directional_skybox_light.slf+2−2
@@ -28,7 +28,7 @@ void main(void) { · 27 unmodified lines
2828 DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
2929
3030 // Light mapped or not ?
31− if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
31+ if (frag.mode == LIGHT_MAPPED) {
3232 vec3 color = evalLightmappedColor(
3333 deferredTransform.viewInverse,
3434 1.0,
@@ -39,7 +39,7 @@ void main(void) { · 4 unmodified lines
3939 } else {
4040 vec3 color = evalSkyboxGlobalColor(
4141 deferredTransform.viewInverse,
42− 1.0,
42+ frag.obscurance,
4343 frag.position.xyz,
4444 frag.normal,
4545 frag.diffuse,
libraries/render-utils/src/ssao.slh+93−2
@@ -11,9 +11,28 @@ · 10 unmodified lines
1111 <@if not SSAO_SLH@>
1212 <@def SSAO_SLH@>
1313
14+<@func declarePackOcclusionDepth()@>
15+
16+const float FAR_PLANE_Z = -300.0;
17+
18+float CSZToDephtKey(float z) {
19+ return clamp(z * (1.0 / FAR_PLANE_Z), 0.0, 1.0);
20+}
21+vec3 packOcclusionDepth(float occlusion, float depth) {
22+ // Round to the nearest 1/256.0
23+ float temp = floor(depth * 256.0);
24+ return vec3(occlusion, temp * (1.0 / 256.0), depth * 256.0 - temp);
25+}
26+vec2 unpackOcclusionDepth(vec3 packed) {
27+ float z = packed.y * (256.0 / 257.0) + packed.z * (1.0 / 257.0);
28+ return vec2(packed.x, z);
29+}
30+<@endfunc@>
31+
1432 <@func declareAmbientOcclusion()@>
1533
1634 struct AmbientOcclusionParams {
35+ vec4 _pixelInfo;
1736 vec4 _clipInfo;
1837 mat4 _projection;
1938 vec4 _radius_radius2_InvRadius6_s2;
@@ -23,8 +42,11 @@ uniform ambientOcclusionParamsBuffer { · 3 unmodified lines
2342 AmbientOcclusionParams params;
2443 };
2544
45+vec2 getWidthHeight() {
46+ return params._pixelInfo.zw;
47+}
2648 float getProjScale() {
27− return 500.0; // this should be viewportHeight * Proj[1][1] / 2.0
49+ return getWidthHeight().y * params._projection[1][1] * 0.5;
2850 }
2951
3052 float getRadius() {
@@ -50,8 +72,77 @@ vec3 evalEyePositionFromZeye(float Zeye, vec2 texcoord) { · 19 unmodified lines
5072 }
5173
5274 vec3 evalEyeNormal(vec3 C) {
53− return normalize(cross(dFdy(C), dFdx(C)));
75+ //return normalize(cross(dFdy(C), dFdx(C)));
76+ return normalize(cross(dFdx(C), dFdy(C)));
5477 }
78+
79+<@endfunc@>
80+
81+<@func declareBlurPass(axis)@>
82+
83+<$declarePackOcclusionDepth()$>
84+
85+// the source occlusion texture
86+uniform sampler2D occlusionMap;
87+
88+vec2 fetchOcclusionDepthRaw(ivec2 coords, out vec3 raw) {
89+ raw = texelFetch(occlusionMap, coords, 0).xyz;
90+ return unpackOcclusionDepth(raw);
91+}
92+
93+vec2 fetchOcclusionDepth(ivec2 coords) {
94+ return unpackOcclusionDepth(texelFetch(occlusionMap, coords, 0).xyz);
95+}
96+
97+
98+const int BLUR_RADIUS = 4;
99+const int RADIUS_SCALE = 2;
100+const float EDGE_SHARPNESS = 1.0;
101+
102+const float gaussian[BLUR_RADIUS + 1] =
103+// float[](0.356642, 0.239400, 0.072410, 0.009869); // R = 2
104+// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // R = 3
105+float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // R = 4
106+// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // R = 5.0
107+
108+vec3 getBlurredOcclusion(vec2 coord) {
109+ ivec2 ssC = ivec2(coord);
110+
111+ vec3 rawSample;
112+ vec2 occlusionDepth = fetchOcclusionDepthRaw(ssC, rawSample);
113+ float key = occlusionDepth.y;
114+ float sum = occlusionDepth.x;
115+
116+ // Base weight for depth falloff. Increase this for more blurriness,
117+ // decrease it for better edge discrimination
118+ float BASE = gaussian[0];
119+ float totalWeight = BASE;
120+ sum *= totalWeight;
121+
122+ for (int r = -BLUR_RADIUS; r <= BLUR_RADIUS; ++r) {
123+ // We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
124+ // so the IF statement has no runtime cost
125+ if (r != 0) {
126+ vec2 tapOZ = fetchOcclusionDepth(ssC + <$axis$> * (r * RADIUS_SCALE));
127+
128+ // spatial domain: offset gaussian tap
129+ float weight = 0.3 + gaussian[abs(r)];
130+
131+ // range domain (the "bilateral" weight). As depth difference increases, decrease weight.
132+ weight *= max(0.0, 1.0 - (EDGE_SHARPNESS * 2000.0) * abs(tapOZ.y - key));
133+
134+ sum += tapOZ.x * weight;
135+ totalWeight += weight;
136+ }
137+ }
138+
139+ const float epsilon = 0.0001;
140+ float result = sum / (totalWeight + epsilon);
141+
142+ rawSample.x = result;
143+ return rawSample;
144+}
145+
55146 <@endfunc@>
56147
57148
libraries/render-utils/src/ssao_makeHorizontalBlur.slf+4−4
@@ -10,14 +10,14 @@ · 9 unmodified lines
1010 //
1111
1212 <@include ssao.slh@>
13−<$declareAmbientOcclusion()$>
1413
15−// the depth texture
16−uniform sampler2D occlusionMap;
14+const ivec2 horizontal = ivec2(1,0);
15+<$declareBlurPass(horizontal)$>
16+
1717
1818 in vec2 varTexCoord0;
1919 out vec4 outFragColor;
2020
2121 void main(void) {
22− outFragColor = texture(occlusionMap, varTexCoord0);
22+ outFragColor = vec4(getBlurredOcclusion(gl_FragCoord.xy), 1.0);
2323 }
libraries/render-utils/src/ssao_makeOcclusion.slf+10−31
@@ -11,6 +11,7 @@ · 10 unmodified lines
1111
1212 <@include ssao.slh@>
1313 <$declareAmbientOcclusion()$>
14+<$declarePackOcclusionDepth()$>
1415
1516 const int NUM_SAMPLES = 11;
1617 const float INV_NUM_SAMPLES = 1.0 / float(NUM_SAMPLES);
@@ -21,34 +22,15 @@ const int MAX_MIP_LEVEL = 5; · 4 unmodified lines
2122 // the depth pyramid texture
2223 uniform sampler2D pyramidMap;
2324
24−float getZeye(vec2 texcoord) {
25− return -texture(pyramidMap, texcoord, 0).x;
26−}
27−
2825 vec3 evalEyePosition(vec2 texcoord) {
29− float Zeye = getZeye(texcoord);
26+ float Zeye = -texture(pyramidMap, texcoord, 0).x;
3027 return evalEyePositionFromZeye(Zeye, texcoord);
3128 }
3229
3330 in vec2 varTexCoord0;
3431 out vec4 outFragColor;
3532
36−/** Used for packing Z into the GB channels */
37−float CSZToKey(float z) {
38− return clamp(z * (1.0 / params._clipInfo.z), 0.0, 1.0);
39−}
40−
41−/** Used for packing Z into the GB channels */
42−void packKey(float key, out vec2 p) {
43− // Round to the nearest 1/256.0
44− float temp = floor(key * 256.0);
45−
46− // Integer part
47− p.x = temp * (1.0 / 256.0);
48−
49− // Fractional part
50− p.y = key * 256.0 - temp;
51−}
33+uniform sampler2D normalMap;
5234
5335 vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
5436 // Radius relative to ssR
@@ -76,7 +58,7 @@ vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { · 21 unmodified lines
7658 // Offset to pixel center
7759 //P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
7860
79− vec2 tapUV = (vec2(ssP) + vec2(0.5)) / textureSize(pyramidMap, 0);
61+ vec2 tapUV = (vec2(ssP) + vec2(0.5)) / getWidthHeight();
8062 P = evalEyePositionFromZeye(P.z, tapUV);
8163 return P;
8264 }
@@ -128,14 +110,11 @@ void main(void) { · 45 unmodified lines
128110
129111 vec3 Cp = evalEyePosition(varTexCoord0);
130112
131− // packKey(CSZToKey(Cp.z), bilateralKey);
132−
133113 // Hash function used in the HPG12 AlchemyAO paper
134114 float randomPatternRotationAngle = (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10;
135− //float randomPatternRotationAngle = 0;
136−
137115
138116 vec3 Cn = evalEyeNormal(Cp);
117+ // vec3 Cn = normalize((texelFetch(normalMap, ssC, 0).xyz * 2.0) - vec3(1.0));
139118
140119 // Choose the screen-space sample radius
141120 // proportional to the projected area of the sphere
@@ -143,20 +122,20 @@ void main(void) { · 1 unmodified line
143122
144123 float sum = 0.0;
145124 for (int i = 0; i < NUM_SAMPLES; ++i) {
146− sum += sampleAO(ssC, Cp, Cn, ssDiskRadius, i, randomPatternRotationAngle);
125+ sum += sampleAO(ssC, Cp, Cn, ssDiskRadius, i, randomPatternRotationAngle);
147126 }
148127
149128 float A = max(0.0, 1.0 - sum * getInvRadius6() * 5.0 * INV_NUM_SAMPLES);
150129
151130 // Bilateral box-filter over a quad for free, respecting depth edges
152131 // (the difference that this makes is subtle)
153− if (abs(dFdx(Cp.z)) < 0.02) {
132+ /*if (abs(dFdx(Cp.z)) < 0.02) {
154133 A -= dFdx(A) * ((ssC.x & 1) - 0.5);
155134 }
156135 if (abs(dFdy(Cp.z)) < 0.02) {
157136 A -= dFdy(A) * ((ssC.y & 1) - 0.5);
158− }
159−
137+ }*/
160138
161− outFragColor = vec4(A, debugValue(Cn.y, 10));
139+ outFragColor = vec4(packOcclusionDepth(A, CSZToDephtKey(Cp.z)), 1.0);
140+ //outFragColor = vec4(0.5 * (Cn + vec3(1.0)), A);
162141 }
libraries/render-utils/src/ssao_makeVerticalBlur.slf+4−5
@@ -8,16 +8,15 @@ · 7 unmodified lines
88 // Distributed under the Apache License, Version 2.0.
99 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
1010 //
11−
1211 <@include ssao.slh@>
13−<$declareAmbientOcclusion()$>
1412
15−// the depth texture
16−uniform sampler2D occlusionMap;
13+const ivec2 vertical = ivec2(0,1);
14+<$declareBlurPass(vertical)$>
1715
1816 in vec2 varTexCoord0;
1917 out vec4 outFragColor;
2018
2119 void main(void) {
22− outFragColor = vec4(0.0, 0.0, 0.0, texture(occlusionMap, varTexCoord0).x);
20+ float occlusion = getBlurredOcclusion(gl_FragCoord.xy).x;
21+ outFragColor = vec4(0.0, 0.0, 0.0, occlusion);
2322 }