From 1139c150555a2da1e6234663d69f57143315176d Mon Sep 17 00:00:00 2001
From: ansgar <ansgar@5a81b35b-ba03-0410-adc8-b2c5c5119f08>
Date: Sat, 8 May 2010 20:34:01 +0000
Subject: [PATCH] tweaks to ambient occlusion

git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/branches/new_gfx@2206 5a81b35b-ba03-0410-adc8-b2c5c5119f08
---
 modules/gfx/pymod/export_scene.cc      |  5 ++-
 modules/gfx/src/impl/scene_fx.cc       | 16 ++++---
 modules/gfx/src/impl/scene_fx.hh       |  1 +
 modules/gfx/src/scene.cc               | 14 ++++++-
 modules/gfx/src/scene.hh               |  5 ++-
 modules/gfx/src/shader/amboccl_fs.glsl | 58 ++++++++++++++++++--------
 6 files changed, 69 insertions(+), 30 deletions(-)

diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index e5e93d5b5..47bd793c0 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -120,9 +120,10 @@ void export_Scene()
     .def("SetShadow",&Scene::SetShadow)
     .def("SetShadowQuality",&Scene::SetShadowQuality)
     .def("SetDepthDarkening",&Scene::SetDepthDarkening)
-    .def("SetDepthDarkeningFactor",&Scene::SetDepthDarkeningFactor)
+    .def("SetDepthDarkeningWeight",&Scene::SetDepthDarkeningWeight)
     .def("SetAmbientOcclusion",&Scene::SetAmbientOcclusion)
-    .def("SetAmbientOcclusionFactor",&Scene::SetAmbientOcclusionFactor)
+    .def("SetAmbientOcclusionWeight",&Scene::SetAmbientOcclusionWeight)
+    .def("SetAmbientOcclusionMode",&Scene::SetAmbientOcclusionMode)
     .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 9e32dc329..5b200f274 100644
--- a/modules/gfx/src/impl/scene_fx.cc
+++ b/modules/gfx/src/impl/scene_fx.cc
@@ -28,6 +28,7 @@ SceneFX::SceneFX():
   depth_dark_factor(1.0),
   amb_occl_flag(false),
   amb_occl_factor(1.0),
+  amb_occl_mode(1),
   scene_tex_id_(),
   depth_tex_id_(),
   shadow_tex_id_(),
@@ -263,8 +264,7 @@ void SceneFX::Postprocess()
     glBindTexture(GL_TEXTURE_2D,shadow_tex_id_);
     glMatrixMode(GL_TEXTURE);
     glPushMatrix();
-    // make explicit object instead of temporary to avoid potential crash with Data()
-    geom::Mat4 ttmp=Transpose(shadow_tex_mat_);
+    geom::Mat4 ttmp=geom::Transpose(shadow_tex_mat_);
     glLoadMatrix(ttmp.Data());
     glMatrixMode(GL_MODELVIEW);
     glActiveTexture(GL_TEXTURE0);
@@ -379,7 +379,7 @@ void SceneFX::prep_shadow_map()
   //glFrustum(tmin[0],tmax[0],tmin[1],tmax[1],-tmax[2],-tmin[2]);
   float glpmat[16];
   glGetv(GL_PROJECTION_MATRIX, glpmat);
-  geom::Mat4 pmat(Transpose(geom::Mat4(glpmat)));
+  geom::Mat4 pmat(geom::Transpose(geom::Mat4(glpmat)));
 
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
@@ -416,7 +416,7 @@ void SceneFX::prep_shadow_map()
   //shadow_tex_mat_ = bias*pmat*ltrans.GetMatrix();
   Scene::Instance().ResetProjection();
   glGetv(GL_PROJECTION_MATRIX, glpmat);
-  geom::Mat4 pmat2(Transpose(geom::Mat4(glpmat)));
+  geom::Mat4 pmat2(geom::Transpose(geom::Mat4(glpmat)));
   /*
     given the normalized coordinates in scenefx, the camera projection and modelview transformation
     are first reverted, and then the light modelview and projection are applied, resulting (with the
@@ -435,7 +435,6 @@ void SceneFX::prep_amb_occlusion()
   Shader::Instance().PushProgram();
   Shader::Instance().Activate("amboccl");
   GLuint cpr=Shader::Instance().GetCurrentProgram();
-  // assign tex units
   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D,depth_tex_id_);
   glActiveTexture(GL_TEXTURE1);
@@ -448,10 +447,15 @@ void SceneFX::prep_amb_occlusion()
   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));
+  glUniform1i(glGetUniformLocation(cpr,"mode"),amb_occl_mode);
   double pm[16];
   glGetDoublev(GL_PROJECTION_MATRIX,pm);
   glUniform4f(glGetUniformLocation(cpr,"abcd"),pm[0],pm[5],pm[10],pm[14]);
-
+  glMatrixMode(GL_TEXTURE);
+  glPushMatrix();
+  geom::Mat4 ipm(geom::Transpose(geom::Invert(geom::Transpose(geom::Mat4(pm)))));
+  glLoadMatrix(ipm.Data());
+  glMatrixMode(GL_MODELVIEW);
 
   // set up viewport filling quad to run the fragment shader
   draw_screen_quad(width,height);
diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh
index 3048e1d52..f24e4596e 100644
--- a/modules/gfx/src/impl/scene_fx.hh
+++ b/modules/gfx/src/impl/scene_fx.hh
@@ -56,6 +56,7 @@ public:
   float depth_dark_factor;
   bool amb_occl_flag;
   float amb_occl_factor;
+  uint amb_occl_mode;
 
 private:
   SceneFX();
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index c11457597..cad6fc603 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -195,7 +195,7 @@ void Scene::SetDepthDarkening(bool f)
 #endif
 }
 
-void Scene::SetDepthDarkeningFactor(float f)
+void Scene::SetDepthDarkeningWeight(float f)
 {
 #if OST_SHADER_SUPPORT_ENABLED
   impl::SceneFX::Instance().depth_dark_factor=f;
@@ -213,7 +213,7 @@ void Scene::SetAmbientOcclusion(bool f)
 #endif
 } 
 
-void Scene::SetAmbientOcclusionFactor(float f)
+void Scene::SetAmbientOcclusionWeight(float f)
 {
 #if OST_SHADER_SUPPORT_ENABLED
   impl::SceneFX::Instance().amb_occl_factor=f;
@@ -222,6 +222,15 @@ void Scene::SetAmbientOcclusionFactor(float f)
 #endif
 }
 
+void Scene::SetAmbientOcclusionMode(uint m)
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  impl::SceneFX::Instance().amb_occl_mode=m;
+  // the redraw routine will deal with the Shader
+  RequestRedraw();
+#endif
+}
+
 void Scene::SetShadingMode(const std::string& smode)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -241,6 +250,7 @@ void Scene::SetShadingMode(const std::string& smode)
   } else {
     Shader::Instance().Activate("fraglight");
   }
+  RequestRedraw();
 #endif
 }
 
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index 397d2dbb3..1b798d24b 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -112,10 +112,11 @@ class DLLEXPORT_OST_GFX Scene {
   void SetShadowQuality(int q);
 
   void SetDepthDarkening(bool f);
-  void SetDepthDarkeningFactor(float f);
+  void SetDepthDarkeningWeight(float f);
 
   void SetAmbientOcclusion(bool f);
-  void SetAmbientOcclusionFactor(float f);
+  void SetAmbientOcclusionWeight(float f);
+  void SetAmbientOcclusionMode(uint m);
   
   /// \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 01f7a7217..894290241 100644
--- a/modules/gfx/src/shader/amboccl_fs.glsl
+++ b/modules/gfx/src/shader/amboccl_fs.glsl
@@ -4,28 +4,51 @@ uniform sampler1D kernel;
 uniform float step;
 uniform vec2 i_vp;
 uniform vec4 abcd;
+uniform int mode;
 
-vec3 unproject(in vec3 scr)
+vec3 unproject(in vec3 rpos)
 { 
-  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);
-  vec4 tmp2 = gl_ProjectionMatrixInverse*vec4(tmp,1.0);
-  return tmp2.xyz/tmp2.w;
+  vec4 coord = gl_TextureMatrix[0]*vec4(rpos.xy*2.0-1.0,rpos.z*2.0-1.0,1.0);
+  return coord.xyz/coord.w;
 }
 
-float ao(in vec2 tab, in vec3 pos_p, in vec3 norm_p, in vec3 t_pos_p)
+float ao(in vec2 tab, in float depth_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);
+  vec2 rpos = gl_TexCoord[0].xy+tab.xy*i_vp;
+  float depth_q = texture2D(depth_map,rpos).r;
+  if(mode==0) {
+    if(depth_q>=depth_p) {
+      return 0.0;
+    } else {
+      return 1.0;
+    }
+  } 
 
+  vec3 t_pos_q = unproject(vec3(rpos.xy,depth_q));
   vec3 diff=t_pos_q-t_pos_p;
-  float fac=1.0+dot(diff,diff)/5.0;
-  return max(0.0,dot(normalize(norm_p),normalize(diff)))/fac;
+  float nd = dot(normalize(norm_p),normalize(diff));
+
+  if(mode==1) {
+    return 1.6*max(0.0,nd);
+  }
+
+  if(mode==2) {
+    float fac=1.0+dot(diff,diff)/100.0;
+    return 1.6*max(0.0,nd)/fac;
+  }
+
+  if(mode==3) {
+    // radius of imposter at distance depth_q to cover a single pixel
+    vec4 tmpv=gl_TextureMatrix[0]*vec4(-1.0,0.0,depth_q,1.0);
+    float tmpd=tmpv.x/tmpv.w;
+    tmpv=gl_TextureMatrix[0]*vec4(1.0,0.0,depth_q,1.0);
+    // 10.0 is a fudge factor
+    float rad=10.0*i_vp[0]*abs(tmpv.x/tmpv.w-tmpd);
+    float s = 6.283*(1.0-sqrt(1.0-min(1.0,rad*rad/dot(diff,diff))));
+    return s*max(0.0,nd);
+  }
+
+  return 0.0;
 }
 
 void main()
@@ -36,14 +59,13 @@ void main()
     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);
+  vec3 t_pos_p = unproject(vec3(gl_TexCoord[0].xy,depth_p));
 
   float i;
   float sum=0.0;
   for(i=0.0;i<1.0;i+=step) {
     vec2 nn=texture1D(kernel,i).xy*40.0-20.0;
-    sum+=ao(nn,pos_p,norm_p,t_pos_p);
+    sum+=ao(nn,depth_p,norm_p,t_pos_p);
   }
   sum*=step;
 
-- 
GitLab