From 79e6e6fab9b4a698a7f1cc3cb23793c6fe570e09 Mon Sep 17 00:00:00 2001
From: Ansgar Philippsen <ansgar.philippsen@gmail.com>
Date: Wed, 5 Sep 2012 18:49:16 -0400
Subject: [PATCH] fixed fog bug in gfx postprocessing

---
 modules/gfx/src/impl/scene_fx.cc       | 22 ++++++++++++++++++----
 modules/gfx/src/impl/scene_fx.hh       |  3 +++
 modules/gfx/src/shader.cc              |  7 ++++++-
 modules/gfx/src/shader/scenefx_fs.glsl | 18 ++++++++++++++++--
 4 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc
index c1f87182e..a9ddbc4cd 100644
--- a/modules/gfx/src/impl/scene_fx.cc
+++ b/modules/gfx/src/impl/scene_fx.cc
@@ -224,6 +224,11 @@ void SceneFX::Preprocess()
   }
 }
 
+bool SceneFX::WillPostprocess() const
+{
+  return shadow_flag || amb_occl_flag || depth_dark_flag || use_beacon;
+}
+
 void SceneFX::Postprocess()
 {
   if(!OST_GL_VERSION_2_0) return;
@@ -235,10 +240,7 @@ void SceneFX::Postprocess()
 #endif
   }
 
-  if(!shadow_flag && !amb_occl_flag && !depth_dark_flag && !use_beacon) {
-    // no postprocessing is needed
-    return;
-  }
+  if(!WillPostprocess()) return;
 
   Viewport vp=Scene::Instance().GetViewport();
 
@@ -329,6 +331,18 @@ void SceneFX::Postprocess()
     glUniform1i(glGetUniformLocation(cpr,"dark_flag"),0);
   }
 
+  GLint fog;
+  glGetIntegerv(GL_FOG,&fog);
+  float znear=Scene::Instance().GetNear();
+  float zfar=Scene::Instance().GetFar();
+  float fnear=znear+Scene::Instance().GetFogNearOffset();
+  float ffar=zfar+Scene::Instance().GetFogFarOffset();
+  glUniform1i(glGetUniformLocation(cpr,"fog_flag"),fog);
+  glUniform1f(glGetUniformLocation(cpr,"depth_near"),znear);
+  glUniform1f(glGetUniformLocation(cpr,"depth_far"),zfar);
+  glUniform1f(glGetUniformLocation(cpr,"fog_far"),ffar);
+  glUniform1f(glGetUniformLocation(cpr,"fog_scale"),1.0f/(ffar-fnear));
+
   if(use_beacon) {
     prep_beacon();
   }
diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh
index 3b8e1fa38..ad8d2a787 100644
--- a/modules/gfx/src/impl/scene_fx.hh
+++ b/modules/gfx/src/impl/scene_fx.hh
@@ -53,6 +53,9 @@ public:
   void Preprocess();
   // assumes scene has been drawn in the active framebuffer
   void Postprocess();
+  
+  // returns true if the post-processing will run
+  bool WillPostprocess() const;
 
   void DrawTex(unsigned int w, unsigned int h, GLuint texid);
 
diff --git a/modules/gfx/src/shader.cc b/modules/gfx/src/shader.cc
index 2a5e91ce2..3ed15cac3 100644
--- a/modules/gfx/src/shader.cc
+++ b/modules/gfx/src/shader.cc
@@ -28,6 +28,7 @@
 #include <ost/platform.hh>
 #include <ost/log.hh>
 
+#include "impl/scene_fx.hh"
 #include "glext_include.hh"
 
 #include "shader.hh"
@@ -366,7 +367,11 @@ void Shader::UpdateState()
     glGetBooleanv(GL_LIGHT_MODEL_TWO_SIDE,&bresult);
     LOG_TRACE("setting two_sided flag to " << bresult);
     glUniform1i(glGetUniformLocation(current_program_,"two_sided_flag"),bresult);
-    glGetIntegerv(GL_FOG,&result);
+    if(impl::SceneFX::Instance().WillPostprocess()) {
+      result=0;
+    } else {
+      glGetIntegerv(GL_FOG,&result);
+    }
     LOG_TRACE("setting fog flag to " << result);
     glUniform1i(glGetUniformLocation(current_program_,"fog_flag"),result);
     glDisable(GL_COLOR_MATERIAL);
diff --git a/modules/gfx/src/shader/scenefx_fs.glsl b/modules/gfx/src/shader/scenefx_fs.glsl
index cb5c2313c..e328d2d08 100644
--- a/modules/gfx/src/shader/scenefx_fs.glsl
+++ b/modules/gfx/src/shader/scenefx_fs.glsl
@@ -13,6 +13,11 @@ uniform float occl_mult;
 uniform bool dark_flag;
 uniform sampler2D dark_map;
 uniform float dark_mult;
+uniform bool fog_flag;
+uniform float depth_near;
+uniform float depth_far;
+uniform float fog_far;
+uniform float fog_scale;
 
 // gl_TexCoord[0] comes from scenefx_vs, i.e. from post processing
 
@@ -55,6 +60,15 @@ void main()
   if(dark_flag) {
     dark_factor=max(0.0,1.0-dark_mult*(1.0-texture2D(dark_map,gl_TexCoord[0].xy).r));
   }
-    
-  gl_FragColor.rgb = shadow_factor*occl_factor*dark_factor*scene_color.rgb;
+
+  float fog=1.0;
+  if(fog_flag) {
+    float z = 2.0*depth_near*depth_far/(-(depth*2.0-1.0)*(depth_far-depth_near)+depth_far+depth_near);
+    fog = clamp((fog_far-z) * fog_scale, 0.0, 1.0);
+  }
+
+  gl_FragColor.rgb = mix(gl_Fog.color.rgb, 
+                         shadow_factor*occl_factor*dark_factor*scene_color.rgb,
+                         fog);
 }
+
-- 
GitLab