diff --git a/Effects/ssao-blur-1.eff b/Effects/ssao-blur-1.eff
new file mode 100644
index 000000000..f5bae695f
--- /dev/null
+++ b/Effects/ssao-blur-1.eff
@@ -0,0 +1,10 @@
+
+
+ Effects/ssao-blur-1
+ Effects/blur
+
+ 4.0
+ 0.0
+ ao-1
+
+
diff --git a/Effects/ssao-blur-2.eff b/Effects/ssao-blur-2.eff
new file mode 100644
index 000000000..c3b630c06
--- /dev/null
+++ b/Effects/ssao-blur-2.eff
@@ -0,0 +1,10 @@
+
+
+ Effects/ssao-blur-2
+ Effects/blur
+
+ 0.0
+ 4.0
+ ao-2
+
+
diff --git a/Effects/ssao.eff b/Effects/ssao.eff
new file mode 100644
index 000000000..31b36f44e
--- /dev/null
+++ b/Effects/ssao.eff
@@ -0,0 +1,84 @@
+
+
+ Effects/ssao
+
+ 1.0
+ 0.0
+ 7.0
+ 0.03
+ 800.0
+
+
+
+
+ 0
+ buffer
+ depth
+
+
+ 1
+ buffer
+ normal
+
+
+ 2
+ buffer
+ spec-emis
+
+
+ 3
+ noise
+
+
+ Shaders/ssao.vert
+ Shaders/ssao.frag
+ Shaders/gbuffer-functions.frag
+
+
+ depth_tex
+ sampler-2d
+ 0
+
+
+ normal_tex
+ sampler-2d
+ 1
+
+
+ spec_emis_tex
+ sampler-2d
+ 2
+
+
+ noise_tex
+ sampler-2d
+ 3
+
+
+ g_scale
+ float
+
+
+
+ g_bias
+ float
+
+
+
+ g_intensity
+ float
+
+
+
+ g_sample_rad
+ float
+
+
+
+ random_size
+ float
+
+
+
+
+
diff --git a/Shaders/ssao.frag b/Shaders/ssao.frag
new file mode 100644
index 000000000..6cbe1b1d7
--- /dev/null
+++ b/Shaders/ssao.frag
@@ -0,0 +1,64 @@
+#version 120
+#extension GL_EXT_gpu_shader4 : enable
+uniform sampler2D normal_tex;
+uniform sampler2D depth_tex;
+uniform sampler2D spec_emis_tex;
+uniform sampler3D noise_tex;
+uniform vec2 fg_BufferSize;
+uniform vec3 fg_Planes;
+uniform vec4 fg_du;
+uniform vec4 fg_dv;
+uniform float g_scale;
+uniform float g_bias;
+uniform float g_intensity;
+uniform float g_sample_rad;
+uniform float random_size;
+uniform unsigned int osg_FrameNumber;
+
+varying vec4 ray;
+
+const vec2 v[4] = vec2[](vec2(1.0,0.0),vec2(-1.0,0.0),vec2(0.0,1.0),vec2(0.0,-1.0));
+
+vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex );
+vec3 normal_decode(vec2 enc);
+
+vec2 getRandom( in vec2 uv ) {
+ unsigned int level = osg_FrameNumber - ((osg_FrameNumber / 64U) * 64U);
+ return normalize( texture3D( noise_tex, vec3(uv*50.0, float(level) / 64.0) ).xy * 0.14 - 0.07 );
+}
+vec3 getPosition(in vec2 uv, in vec2 uv0, in vec4 ray0) {
+ vec2 duv = uv - uv0;
+ vec4 ray = ray0 + fg_du * duv.x + fg_dv * duv.y;
+ vec3 viewDir = normalize( ray.xyz );
+ return position(viewDir, uv, depth_tex);
+}
+float doAmbientOcclusion(in vec2 tcoord, in vec2 uv, in vec3 p, in vec3 cnorm, in vec4 ray) {
+ vec3 diff = getPosition(tcoord+uv,tcoord,ray)-p;
+ float d = length(diff);
+ vec3 v = diff / d;
+ d *= g_scale;
+ return max(0.0, dot( cnorm,v ) - g_bias) * (1.0/(1.0+d)) * g_intensity;
+}
+void main() {
+ vec2 coords = gl_TexCoord[0].xy;
+ float initialized = texture2D( spec_emis_tex, coords ).a;
+ if ( initialized < 0.1 )
+ discard;
+ vec3 normal = normal_decode(texture2D( normal_tex, coords ).rg);
+ vec3 viewDir = normalize(ray.xyz);
+ vec3 pos = position(viewDir, coords, depth_tex);
+ vec2 rand = getRandom(coords);
+ float ao = 0.0;
+ float rad = g_sample_rad;
+ int iterations = 4;
+ for (int j = 0; j < 1; ++j ) {
+ vec2 coord1 = reflect( v[j], rand ) * rad;
+ vec2 coord2 = vec2( coord1.x*0.707 - coord1.y*0.707, coord1.x*0.707 + coord1.y*0.707 );
+ ao += doAmbientOcclusion(coords,coord1*0.25,pos,normal,ray);
+ ao += doAmbientOcclusion(coords,coord2*0.5,pos,normal,ray);
+ ao += doAmbientOcclusion(coords,coord1*0.75,pos,normal,ray);
+ ao += doAmbientOcclusion(coords,coord2,pos,normal,ray);
+ }
+ ao /= 16.0;
+ gl_FragColor = vec4( vec3(1.0 - ao), 1.0 );
+}
diff --git a/Shaders/ssao.vert b/Shaders/ssao.vert
new file mode 100644
index 000000000..1d54fcbf5
--- /dev/null
+++ b/Shaders/ssao.vert
@@ -0,0 +1,7 @@
+uniform mat4 fg_ProjectionMatrixInverse;
+varying vec4 ray;
+void main() {
+ gl_Position = gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ ray = fg_ProjectionMatrixInverse * gl_Vertex;
+}