diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index f5658f464db25b7661aa0d3e1695d35186c62895..cd7a902a292b4cc2dafe1172ed5d479081ad99f5 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -119,6 +119,7 @@ void export_Scene()
     .def("SetShadowQuality",&Scene::SetShadowQuality)
     .def("SetDepthDarkening",&Scene::SetDepthDarkening)
     .def("SetAmbientOcclusion",&Scene::SetAmbientOcclusion)
+    .def("SetAmbientOcclusionFactor",&Scene::SetAmbientOcclusionFactor)
     .def("AttachObserver",&Scene::AttachObserver)
     .def("StartOffscreenMode",&Scene::StartOffscreenMode)
     .def("StopOffscreenMode",&Scene::StopOffscreenMode)
diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc
index 08b0ed4c4a370c18bcd70870fd0c2b47b79cd9d8..4c70d8417291f903256d69b6f85bfd3355aae205 100644
--- a/modules/gfx/src/impl/scene_fx.cc
+++ b/modules/gfx/src/impl/scene_fx.cc
@@ -1,3 +1,5 @@
+#include <boost/random.hpp>
+
 #include "scene_fx.hh"
 
 #include <ost/log.hh>
@@ -8,6 +10,11 @@
 
 namespace ost { namespace gfx { namespace impl {
 
+namespace {
+  boost::mt19937 RandomGenerator(time(NULL));
+  boost::uniform_01<boost::mt19937> UniformRandom(RandomGenerator);
+}
+
 SceneFX& SceneFX::Instance()
 {
   static SceneFX inst;
@@ -19,12 +26,15 @@ SceneFX::SceneFX():
   shadow_quality(1),
   depth_dark_flag(false),
   amb_occl_flag(false),
+  amb_occl_factor(1.0),
   scene_tex_id_(),
   depth_tex_id_(),
   shadow_tex_id_(),
   occl_tex_id_(),
   dark_tex_id_(),
   norm_tex_id_(),
+  kernel_tex_id_(),
+  kernel_size_(0),
   scene_tex2_id_(),
   norm_tex2_id_(),
   scene_fb_(),
@@ -45,14 +55,13 @@ void SceneFX::Setup()
   glGenTextures(1,&occl_tex_id_);
   glGenTextures(1,&dark_tex_id_);
   glGenTextures(1,&norm_tex_id_);
+  glGenTextures(1,&kernel_tex_id_);
 
   glGenFramebuffers(1,&scene_fb_);
   glGenRenderbuffers(1,&depth_rb_);
   glGenTextures(1,&scene_tex2_id_);
   glGenTextures(1,&norm_tex2_id_);
 
-  glActiveTexture(GL_TEXTURE0);
-
   glBindTexture(GL_TEXTURE_2D, scene_tex_id_);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -72,14 +81,14 @@ void SceneFX::Setup()
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
   glBindTexture(GL_TEXTURE_2D, occl_tex_id_);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
   glBindTexture(GL_TEXTURE_2D, dark_tex_id_);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
@@ -89,6 +98,29 @@ void SceneFX::Setup()
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
+  glActiveTexture(GL_TEXTURE0);
+  glBindTexture(GL_TEXTURE_1D, kernel_tex_id_);
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  
+  std::vector<GLfloat> tmp;
+  for(int u=-20;u<=20;++u) {
+    for(int v=-20;v<=20;++v) {
+      if(UniformRandom()<0.1) {
+	// norm to 1
+	float x = static_cast<float>(u+20)*0.025;
+	float y = static_cast<float>(v+20)*0.025;
+	tmp.push_back(x);
+	tmp.push_back(y);
+	tmp.push_back(0.0);
+	tmp.push_back(0.0);
+      }
+    }
+  }
+
+  kernel_size_=tmp.size()/4;
+  glTexImage1D(GL_TEXTURE_1D,0,4,kernel_size_,0,GL_RGBA, GL_FLOAT, &tmp[0]);
 }
 
 void SceneFX::Resize(unsigned int w, unsigned int h)
@@ -149,9 +181,9 @@ void SceneFX::Postprocess()
       Shader::Instance().Activate("dumpnorm");
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       Scene::Instance().GetRootNode()->RenderGL(STANDARD_RENDER_PASS);
-      Shader::Instance().PopProgram();
       glBindTexture(GL_TEXTURE_2D, norm_tex_id_);
-      glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, vp.x, vp.y, vp.width, vp.height, 0);
+      glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vp.x, vp.y, vp.width, vp.height, 0);
+      Shader::Instance().PopProgram();
     }
   }
 
@@ -160,8 +192,6 @@ void SceneFX::Postprocess()
   }
   if(amb_occl_flag) {
     prep_amb_occlusion();
-    draw_debug_tex(vp.width,vp.height,occl_tex_id_);
-    return;
   }
   if(depth_dark_flag) {
     //prep_depth_darkening();
@@ -170,12 +200,13 @@ void SceneFX::Postprocess()
 
   Shader::Instance().PushProgram();
   glEnable(GL_TEXTURE_2D);
+  glEnable(GL_TEXTURE_1D);
   Shader::Instance().Activate("scenefx");
+  GLuint cpr=Shader::Instance().GetCurrentProgram();
   glActiveTexture(GL_TEXTURE1);
   glBindTexture(GL_TEXTURE_2D,depth_tex_id_);
   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D,scene_tex_id_);
-  GLuint cpr=Shader::Instance().GetCurrentProgram();
   glUniform1i(glGetUniformLocation(cpr,"scene"),0);
   glUniform1i(glGetUniformLocation(cpr,"depth"),1);
   glUniform2f(glGetUniformLocation(cpr,"scalef"),
@@ -196,16 +227,15 @@ void SceneFX::Postprocess()
   } else {
     glUniform1i(glGetUniformLocation(cpr,"shadow_flag"),0);
   }
-#if 0
   if(amb_occl_flag) {
     glActiveTexture(GL_TEXTURE3);
     glBindTexture(GL_TEXTURE_2D,occl_tex_id_);
     glUniform1i(glGetUniformLocation(cpr,"occl_flag"),1);
     glUniform1i(glGetUniformLocation(cpr,"occl_map"),3);
+    glUniform1f(glGetUniformLocation(cpr,"occl_mult"),amb_occl_factor);
   } else {
     glUniform1i(glGetUniformLocation(cpr,"occl_flag"),0);
   }
-#endif
 
   draw_screen_quad(vp.width,vp.height);
   glDisable(GL_TEXTURE_2D);
@@ -289,6 +319,9 @@ void SceneFX::prep_amb_occlusion()
 {
   Viewport vp=Scene::Instance().GetViewport();
 
+  uint width=vp.width/2;
+  uint height=vp.height/2;
+
   Shader::Instance().PushProgram();
   Shader::Instance().Activate("amboccl");
   GLuint cpr=Shader::Instance().GetCurrentProgram();
@@ -297,15 +330,23 @@ void SceneFX::prep_amb_occlusion()
   glBindTexture(GL_TEXTURE_2D,depth_tex_id_);
   glActiveTexture(GL_TEXTURE1);
   glBindTexture(GL_TEXTURE_2D,norm_tex_id_);
-  glUniform1i(glGetUniformLocation(cpr,"depth"),0);
-  glUniform1i(glGetUniformLocation(cpr,"norm"),1);
+  glActiveTexture(GL_TEXTURE2);
+  glBindTexture(GL_TEXTURE_1D,kernel_tex_id_);
+  glUniform1i(glGetUniformLocation(cpr,"depth_map"),0);
+  glUniform1i(glGetUniformLocation(cpr,"norm_map"),1);
+  glUniform1i(glGetUniformLocation(cpr,"kernel"),2);
+  glUniform1f(glGetUniformLocation(cpr,"step"),1.0/static_cast<float>(kernel_size_));
+  glUniform2f(glGetUniformLocation(cpr,"i_vp"),1.0/static_cast<float>(width),1.0/static_cast<float>(height));
+  double pm[16];
+  glGetDoublev(GL_PROJECTION_MATRIX,pm);
+  glUniform4f(glGetUniformLocation(cpr,"abcd"),pm[0],pm[5],pm[10],pm[14]);
 
   // set up viewport filling quad to run the fragment shader
-  draw_screen_quad(vp.width,vp.height);
+  draw_screen_quad(width,height);
 
-  glActiveTexture(GL_TEXTURE0);
+  glActiveTexture(GL_TEXTURE3);
   glBindTexture(GL_TEXTURE_2D, occl_tex_id_);
-  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0,0, vp.width, vp.height, 0);
+  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0,0, width, height, 0);
 
   Shader::Instance().PopProgram();
 }
diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh
index 6db023e03987e0fbe34ac41e51ef9cf3f2304619..884ae425a9bdefed8053b012c7bcb3610e145012 100644
--- a/modules/gfx/src/impl/scene_fx.hh
+++ b/modules/gfx/src/impl/scene_fx.hh
@@ -50,6 +50,7 @@ public:
   int shadow_quality;
   bool depth_dark_flag;
   bool amb_occl_flag;
+  float amb_occl_factor;
 
 private:
   SceneFX();
@@ -68,6 +69,8 @@ private:
   GLuint occl_tex_id_;
   GLuint dark_tex_id_;
   GLuint norm_tex_id_;
+  GLuint kernel_tex_id_;
+  uint kernel_size_;
 
   GLuint scene_tex2_id_;
   GLuint norm_tex2_id_;
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index 6c8bbded8a36d710529892a2d4b33682600aefef..028b78fbd2c7cbdb76c036c1d4c1ddd268360ac2 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -198,6 +198,15 @@ void Scene::SetAmbientOcclusion(bool f)
   // the redraw routine will deal with the Shader
   RequestRedraw();
 #endif
+} 
+
+void Scene::SetAmbientOcclusionFactor(float f)
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  impl::SceneFX::Instance().amb_occl_factor=f;
+  // the redraw routine will deal with the Shader
+  RequestRedraw();
+#endif
 }
 
 void Scene::SetShadingMode(const std::string& smode)
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index 17182a20e7ab931e1913bfddb1e5fff9702ae82b..bedf2774fef15c02ae88c7cd39e269ea838a22e7 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -114,6 +114,7 @@ class DLLEXPORT_OST_GFX Scene {
   void SetDepthDarkening(bool f);
 
   void SetAmbientOcclusion(bool f);
+  void SetAmbientOcclusionFactor(float f);
   
   /// \brief select shading mode
   /// one of fallback, basic, default, hf, toon1, toon2
diff --git a/modules/gfx/src/shader/amboccl_fs.glsl b/modules/gfx/src/shader/amboccl_fs.glsl
index 1a6a365def90e6e9b7c845c40affbde8ad95f1d1..b1a8be162a5d25181a828f3a16623d1e1474bb1f 100644
--- a/modules/gfx/src/shader/amboccl_fs.glsl
+++ b/modules/gfx/src/shader/amboccl_fs.glsl
@@ -1,9 +1,51 @@
-uniform sampler2D depth;
-uniform sampler2D norm;
+uniform sampler2D depth_map;
+uniform sampler2D norm_map;
+uniform sampler1D kernel;
+uniform float step;
+uniform vec2 i_vp;
+uniform vec4 abcd;
+
+vec3 unproject(in vec3 scr)
+{ 
+  vec3 tmp=vec3(scr.x*i_vp.x*2.0-1.0,scr.y*i_vp.y*2.0-1.0,scr.z);
+  float iw = 1.0/(tmp.z/abcd.w+abcd.z/abcd.w);
+  return iw*vec3(tmp.x/abcd.x,tmp.y/abcd.y,-1.0);
+}
+
+float ao(in vec2 tab, in vec3 pos_p, in vec3 norm_p, in vec3 t_pos_p)
+{
+  float depth_q = texture2D(depth_map,gl_TexCoord[0].xy+tab.xy*i_vp).r;
+  if(depth_q>=1.0) {
+    return 0.0;
+  }
+  vec3 pos_q = vec3(gl_FragCoord.xy+tab.xy,depth_q);
+  vec3 t_pos_q = unproject(pos_q);
+
+  vec3 diff=t_pos_q-t_pos_p;
+  float fac=1.0+dot(diff,diff)/25.0;
+  return max(0.0,dot(normalize(norm_p),normalize(diff)))/fac;
+}
 
 void main()
 {
-  float val = texture2D(depth,gl_TexCoord[0].xy).r;
-  gl_FragColor.rgb=vec3(val,val,val);
+  float depth_p = texture2D(depth_map,gl_TexCoord[0].xy).r;
+  if(depth_p>=1.0) {
+    gl_FragColor = vec4(0,0,0,1);
+    return;
+  }
+  vec3 norm_p = (texture2D(norm_map,gl_TexCoord[0].xy).xyz-0.5)*2.0;
+  vec3 pos_p = vec3(gl_FragCoord.xy,depth_p);
+  vec3 t_pos_p = unproject(pos_p);
+
+  float i;
+  float sum=0.0;
+  for(i=0.0;i<1.0;i+=step) {
+    vec2 nn=texture1D(kernel,i).xy;
+    nn=(nn-0.5)*40.0;
+    sum+=ao(nn,pos_p,norm_p,t_pos_p);
+  }
+  sum*=step;
+
+  gl_FragColor.rgb=vec3(sum,sum,sum);
   gl_FragColor.a=1.0;
 }
diff --git a/modules/gfx/src/shader/scenefx_fs.glsl b/modules/gfx/src/shader/scenefx_fs.glsl
index 83cc911d22c2a4c523ba629d0bef5a0a820053e3..ce63193f1cc7e48dbce6a74363bffaf97eb8335b 100644
--- a/modules/gfx/src/shader/scenefx_fs.glsl
+++ b/modules/gfx/src/shader/scenefx_fs.glsl
@@ -9,6 +9,7 @@ uniform float shadow_epsilon;
 uniform float shadow_multiplier;
 uniform bool occl_flag;
 uniform sampler2D occl_map;
+uniform float occl_mult;
 
 float CalcShadowFactor(in vec4 coord, in vec2 o)
 {
@@ -33,7 +34,7 @@ void main()
 
   float occl_factor=1.0;
   if(occl_flag) {
-    occl_factor=texture2D(occl_map,gl_TexCoord[0].xy).r;
+    occl_factor=max(0.0,1.0-occl_mult*texture2D(occl_map,gl_TexCoord[0].xy).r);
   }
     
   vec4 scene_color=texture2D(scene,gl_TexCoord[0].xy);