ecere/gfx/drivers/OpenGL: Fixed two-sided lighting
authorJerome St-Louis <jerome@ecere.com>
Fri, 11 Sep 2015 14:21:03 +0000 (23:21 +0900)
committerJerome St-Louis <jerome@ecere.com>
Thu, 15 Oct 2015 00:26:39 +0000 (20:26 -0400)
- Proper calculations checking gl_FrontFacing in the fragment shader
- No need to save compute a separate light, just negate normal
- Including specular higlights for back face as well

ecere/src/gfx/drivers/gl3/fixed.frag
ecere/src/gfx/drivers/gl3/fixed.vertex
ecere/src/gfx/drivers/gl3/matrixStack.ec
ecere/src/gfx/drivers/gl3/shading.ec

index 5d11323..0a8b92c 100644 (file)
@@ -2,14 +2,18 @@
 
 uniform sampler2D diffuseTex;
 uniform bool texturingOn;
+uniform bool lightingOn;
 uniform mat4 texture_matrix;
+uniform bool matTwoSided;
 
 in vec2 fTexCoord;
 in vec4 fColor;
+in vec4 fColorBack;
 
 out vec4 fragColor;
 
 void main(void)
 {
-   fragColor = texturingOn ? fColor * texture(diffuseTex, (vec4(fTexCoord, 0, 1) * texture_matrix).xy) : fColor;
+   vec4 c = (matTwoSided && lightingOn && !gl_FrontFacing) ? fColorBack : fColor;
+   fragColor = texturingOn ? c * texture(diffuseTex, (vec4(fTexCoord, 0, 1) * texture_matrix).xy) : c;
 }
index d696727..7d42ad3 100644 (file)
@@ -7,7 +7,6 @@ uniform vec4 current_color;
 // Lights
 uniform bool lightsOn[8];
 uniform vec4 lightsPos[8];
-uniform vec4 lightsPosI[8];
 
 uniform vec3 lightsDiffuse[8];
 uniform vec3 lightsAmbient[8];
@@ -33,6 +32,7 @@ in vec4 color;
 
 out vec2 fTexCoord;
 out vec4 fColor;
+out vec4 fColorBack;
 
 void main(void)
 {
@@ -47,27 +47,27 @@ void main(void)
       vec3 ambientColor = perVertexColor ? color.xyz : matAmbient;
       float opacity = perVertexColor ? color.w : matOpacity;
       vec3 c = vec3(0);
+      vec3 c2 = vec3(0);
       vec3 ecPosition3 = vec3(gl_Position) / gl_Position.w;
       vec3 eye = vec3(0.0, 0.0, 1.0);
 
       fColor = vec4(0);
+      if(matTwoSided)
+         fColorBack = vec4(0);
       for(i = 0; i < 8; i++)
          if(lightsOn[i])
          {
             vec4 l = lightsPos[i];
             float d = dot(n, l.xyz);
             float pf = 0;
-            if(matTwoSided)
-            {
-               float d2 = dot(n, lightsPosI[i].xyz);
-               if(d2 > d)
-                  d = d2;
-            }
+            vec3 VP = l.xyz;
+            vec3 halfVector;
             if(matPower != 0.0)
             {
-               vec3 VP = l.xyz;
-               vec3 halfVector = normalize(VP + eye);
-               float nDotVP = max(0, dot(n, VP));
+               float nDotVP;
+               VP = l.xyz;
+               halfVector = normalize(VP + eye);
+               nDotVP = max(0, dot(n, VP));
                if(nDotVP != 0.0)
                {
                   float nDotHV = max(0.0, dot(n, halfVector));
@@ -78,11 +78,37 @@ void main(void)
             c += diffuseColor * min(1, max(0, d)) * lightsDiffuse[i];
             c += matSpecular * pf * lightsSpecular[i];
             c += matAmbient * lightsAmbient[i];
+
+            if(matTwoSided)
+            {
+               vec3 iN = -n;
+               float d2 = dot(iN, l.xyz);
+               if(matPower != 0.0)
+               {
+                  float nDotVP = max(0, dot(iN, VP));
+                  if(nDotVP != 0.0)
+                  {
+                     float nDotHV = max(0.0, dot(iN, halfVector));
+                     pf = pow(nDotHV, matPower);
+                  }
+               }
+
+               c2 += diffuseColor * min(1, max(0, d2)) * lightsDiffuse[i];
+               c2 += matSpecular * pf * lightsSpecular[i];
+               c2 += matAmbient * lightsAmbient[i];
+            }
          }
 
       c += ambientColor * globalAmbient;
       c += matEmissive;
       fColor = vec4(c, opacity);
+
+      if(matTwoSided)
+      {
+         c2 += ambientColor * globalAmbient;
+         c2 += matEmissive;
+         fColorBack = vec4(c2, opacity);
+      }
    }
    else
       fColor = current_color * color;
index 9c571f7..c48eff1 100644 (file)
@@ -74,9 +74,9 @@ public void glmsSetNearPlane(double value)
    nearPlane = value;
 }
 
-static Matrix matrixStack[3][32];
-static int matrixIndex[3];
-static int curStack = 0;
+/*static */Matrix matrixStack[3][32];
+/*static */int matrixIndex[3];
+/*static */int curStack = 0;
 
 static void LoadCurMatrix()
 {
index 1f77fe4..0ec7c4b 100644 (file)
@@ -20,7 +20,6 @@ int uLightingOn;
 int uGlobalAmbient;
 int uLightsOn[8];
 int uLightsPos[8];
-int uLightsPosI[8];
 int uLightsDiffuse[8];
 int uLightsAmbient[8];
 int uLightsSpecular[8];
@@ -165,38 +164,20 @@ void shader_setLight(Display display, uint id, Light light)
       }
       else
       {
-         Vector3Df l, li;
+         Vector3Df l;
          Vector3Df vector { 0,0,-1 };
-         Vector3Df vectorI { 0,0, 1 };
-         Vector3Df direction, directionI;
+         Vector3Df direction;
          Matrix mat;
+         Matrix m = matrixStack[0][matrixIndex[0]];
+         m.Scale(nearPlane, nearPlane, nearPlane);
 
          mat.RotationQuaternion(light.orientation);
          direction.MultMatrix(vector, mat);
-         directionI.MultMatrix(vectorI, mat);
 
-         if(!display.display3D || !display.display3D.camera)
-         {
-            // Light in View Space (SetLight before setting camera)
-            l.Normalize(direction);
-            l.z *= -1;
+         vector.MultMatrix(direction, m);
+         l.Normalize(vector);
 
-            li.Normalize(directionI);
-            li.z *= -1;
-         }
-         else
-         {
-            // Light in World Space (SetLight after setting camera)
-            Matrix m = display.display3D.camera.viewMatrix;
-            m.Scale(1,1,-1);
-            vector.MultMatrix(direction, m);
-            l.Normalize(vector);
-
-            vectorI.MultMatrix(directionI, m);
-            li.Normalize(vectorI);
-         }
          glUniform4f(uLightsPos[id], l.x, l.y, l.z, 0);
-         glUniform4f(uLightsPosI[id], li.x, li.y, li.z, 0);
       }
    }
    else
@@ -326,9 +307,6 @@ void loadShaders(const String vertexShaderFile, const String fragmentShaderFile)
          sprintf(name, "lightsPos[%d]", i);
          uLightsPos[i] = glGetUniformLocation(program, name);
 
-         sprintf(name, "lightsPosI[%d]", i);
-         uLightsPosI[i] = glGetUniformLocation(program, name);
-
          sprintf(name, "lightsDiffuse[%d]", i);
          uLightsDiffuse[i] = glGetUniformLocation(program, name);