ecere/gfx/drivers/OpenGL: Exponential fog support in vertex shader
authorJerome St-Louis <jerome@ecere.com>
Fri, 25 Sep 2015 15:55:26 +0000 (11:55 -0400)
committerJerome St-Louis <jerome@ecere.com>
Thu, 15 Oct 2015 00:26:42 +0000 (20:26 -0400)
- Also tweak to disable color array on unsetting camera to fix colors blending in shaders mode

ecere/src/gfx/drivers/OpenGLDisplayDriver.ec
ecere/src/gfx/drivers/gl3/fixed.vertex
ecere/src/gfx/drivers/gl3/shading.ec

index 23b8479..8313c0b 100644 (file)
@@ -461,6 +461,15 @@ public void GLSetupTexturing(bool enable)
 #endif
 }
 
+public void GLSetupFog(bool enable)
+{
+#ifdef SHADERS
+   shader_fog(enable);
+#elif !defined(EM_MODE)
+   (enable ? glEnable : glDisable)(GL_FOG);
+#endif
+}
+
 public void GLSetupLighting(bool enable)
 {
 #if defined(SHADERS)
@@ -2662,14 +2671,18 @@ class OpenGLDisplayDriver : DisplayDriver
             break;
          case fogColor:
          {
-#if !defined(SHADERS)
             float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
+#if defined(SHADERS)
+            shader_fogColor(color[0], color[1], color[2]);
+#else
             glFogfv(GL_FOG_COLOR, (float *)&color);
 #endif
             break;
          }
          case fogDensity:
-#if !defined(SHADERS)
+#if defined(SHADERS)
+            shader_fogDensity((float)(RenderStateFloat { ui = value }.f * nearPlane));
+#else
             glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane));
 #endif
             break;
@@ -2940,6 +2953,7 @@ class OpenGLDisplayDriver : DisplayDriver
       }
       else if(display.display3D.camera)
       {
+         nearPlane = 1;
          oglDisplay.depthWrite = false;
          glViewport(0,0,display.width,display.height);
 
@@ -2948,8 +2962,11 @@ class OpenGLDisplayDriver : DisplayDriver
 
          GLSetupTexturing(false);
          GLSetupLighting(false);
+         GLSetupFog(false);
+
+         glDisableClientState(GL_COLOR_ARRAY);
+
 #if !defined(SHADERS) && !defined(EM_MODE)
-         glDisable(GL_FOG);
          glShadeModel(GL_FLAT);
 #endif
          glEnable(GL_BLEND);
@@ -2985,13 +3002,8 @@ class OpenGLDisplayDriver : DisplayDriver
          glEnable(GL_CULL_FACE);
       }
 
-#if !defined(SHADERS)
       // Fog
-      if(material.flags.noFog)
-         glDisable(GL_FOG);
-      else
-         glEnable(GL_FOG);
-#endif
+      GLSetupFog(!material.flags.noFog);
 
       // Maps
       if(material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))
index 7d42ad3..62cf8f1 100644 (file)
@@ -25,6 +25,11 @@ uniform float matOpacity;
 uniform float matPower;
 uniform bool matTwoSided;
 
+// Fog
+uniform bool fogOn;
+uniform float fogDensity;
+uniform vec3 fogColor;
+
 in vec2 texCoord;
 in vec3 vertex;
 in vec3 normal;
@@ -36,10 +41,16 @@ out vec4 fColorBack;
 
 void main(void)
 {
+   float f = 1;
    vec3 n = normalize(mat3x3(modelview_matrix) * normal);
-   gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 1.0);
+   vec4 pos = modelview_matrix * vec4(vertex, 1.0);
+
+   gl_Position = projection_matrix * pos;
    fTexCoord = texCoord;
 
+   if(fogOn)
+      f = clamp(exp(fogDensity * pos.z), 0, 1);
+
    if(lightingOn)
    {
       int i;
@@ -48,7 +59,7 @@ void main(void)
       float opacity = perVertexColor ? color.w : matOpacity;
       vec3 c = vec3(0);
       vec3 c2 = vec3(0);
-      vec3 ecPosition3 = vec3(gl_Position) / gl_Position.w;
+      // vec3 ecPosition3 = vec3(gl_Position) / gl_Position.w;
       vec3 eye = vec3(0.0, 0.0, 1.0);
 
       fColor = vec4(0);
@@ -103,13 +114,24 @@ void main(void)
       c += matEmissive;
       fColor = vec4(c, opacity);
 
+      if(fogOn)
+         fColor = f * fColor + (1-f) * vec4(fogColor, 1);
+
       if(matTwoSided)
       {
          c2 += ambientColor * globalAmbient;
          c2 += matEmissive;
          fColorBack = vec4(c2, opacity);
+
+         if(fogOn)
+            fColorBack = f * fColorBack + (1-f) * vec4(fogColor, 1);
       }
    }
    else
+   {
       fColor = current_color * color;
+
+      if(fogOn)
+         fColor = f * fColor + (1-f) * vec4(fogColor, 1);
+   }
 }
index 83ccb02..28ad774 100644 (file)
@@ -29,6 +29,9 @@ int uTextureMatrix;
 int uColor;
 int uTexturingOn;
 int uLightingOn;
+int uFogOn;
+int uFogDensity;
+int uFogColor;
 int uGlobalAmbient;
 int uLightsOn[8];
 int uLightsPos[8];
@@ -69,6 +72,21 @@ void shader_lighting(bool on)
    glUniform1ui(uLightingOn, on);
 }
 
+void shader_fog(bool on)
+{
+   glUniform1ui(uFogOn, on);
+}
+
+void shader_fogDensity(float density)
+{
+   glUniform1f(uFogDensity, density);
+}
+
+void shader_fogColor(float r, float g, float b)
+{
+   glUniform3f(uFogColor, r, g, b);
+}
+
 void shader_texturing(bool on)
 {
    glUniform1ui(uTexturingOn, on);
@@ -299,6 +317,9 @@ void loadShaders(const String vertexShaderFile, const String fragmentShaderFile)
       uColor         = glGetUniformLocation(program, "current_color");
       uTexturingOn   = glGetUniformLocation(program, "texturingOn");
       uLightingOn    = glGetUniformLocation(program, "lightingOn");
+      uFogOn         = glGetUniformLocation(program, "fogOn");
+      uFogDensity    = glGetUniformLocation(program, "fogDensity");
+      uFogColor      = glGetUniformLocation(program, "fogColor");
       uGlobalAmbient = glGetUniformLocation(program, "globalAmbient");
       uPerVertexColor  = glGetUniformLocation(program, "perVertexColor");
       uMatDiffuse       = glGetUniformLocation(program, "matDiffuse");