ecere/gfx/drivers/OpenGL: Materials & Light colors support
authorJerome St-Louis <jerome@ecere.com>
Tue, 8 Sep 2015 22:05:56 +0000 (06:05 +0800)
committerJerome St-Louis <jerome@ecere.com>
Thu, 15 Oct 2015 00:26:38 +0000 (20:26 -0400)
ecere/src/gfx/drivers/OpenGLDisplayDriver.ec
ecere/src/gfx/drivers/gl3/fixed.vertex
ecere/src/gfx/drivers/gl3/shading.ec

index 4e87907..cd21972 100644 (file)
@@ -2967,7 +2967,9 @@ class OpenGLDisplayDriver : DisplayDriver
       else
          GLSetupTexturing(false);
 
-#if defined(EM_MODE) || defined(SHADERS)
+#if defined(SHADERS)
+      shader_setMaterial(material, mesh.flags.colors);
+#elif defined(EM_MODE)
       glimtkColor4f(material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity);
 #else
       if(mesh.flags.colors)
index ee92422..d696727 100644 (file)
@@ -7,14 +7,25 @@ uniform vec4 current_color;
 // Lights
 uniform bool lightsOn[8];
 uniform vec4 lightsPos[8];
+uniform vec4 lightsPosI[8];
 
-uniform vec4 lightsDiffuse[8];
-uniform vec4 lightsAmbient[8];
-uniform vec4 lightsSpecular[8];
+uniform vec3 lightsDiffuse[8];
+uniform vec3 lightsAmbient[8];
+uniform vec3 lightsSpecular[8];
 
-uniform vec4 globalAmbient;
+uniform vec3 globalAmbient;
 uniform bool lightingOn;
 
+// Material
+uniform bool perVertexColor;
+uniform vec3 matDiffuse;
+uniform vec3 matAmbient;
+uniform vec3 matSpecular;
+uniform vec3 matEmissive;
+uniform float matOpacity;
+uniform float matPower;
+uniform bool matTwoSided;
+
 in vec2 texCoord;
 in vec3 vertex;
 in vec3 normal;
@@ -32,17 +43,46 @@ void main(void)
    if(lightingOn)
    {
       int i;
-      vec4 diffuseColor = current_color * color;
-      vec4 ambientColor = diffuseColor;
+      vec3 diffuseColor = perVertexColor ? color.xyz : matDiffuse;
+      vec3 ambientColor = perVertexColor ? color.xyz : matAmbient;
+      float opacity = perVertexColor ? color.w : matOpacity;
+      vec3 c = vec3(0);
+      vec3 ecPosition3 = vec3(gl_Position) / gl_Position.w;
+      vec3 eye = vec3(0.0, 0.0, 1.0);
 
       fColor = vec4(0);
       for(i = 0; i < 8; i++)
          if(lightsOn[i])
          {
             vec4 l = lightsPos[i];
-            fColor += diffuseColor * min(1, max(0, dot(n, l.xyz))) * lightsDiffuse[i];
+            float d = dot(n, l.xyz);
+            float pf = 0;
+            if(matTwoSided)
+            {
+               float d2 = dot(n, lightsPosI[i].xyz);
+               if(d2 > d)
+                  d = d2;
+            }
+            if(matPower != 0.0)
+            {
+               vec3 VP = l.xyz;
+               vec3 halfVector = normalize(VP + eye);
+               float nDotVP = max(0, dot(n, VP));
+               if(nDotVP != 0.0)
+               {
+                  float nDotHV = max(0.0, dot(n, halfVector));
+                  pf = pow(nDotHV, matPower);
+               }
+            }
+
+            c += diffuseColor * min(1, max(0, d)) * lightsDiffuse[i];
+            c += matSpecular * pf * lightsSpecular[i];
+            c += matAmbient * lightsAmbient[i];
          }
-      fColor += ambientColor * globalAmbient;
+
+      c += ambientColor * globalAmbient;
+      c += matEmissive;
+      fColor = vec4(c, opacity);
    }
    else
       fColor = current_color * color;
index 44676f5..1f77fe4 100644 (file)
@@ -20,9 +20,18 @@ int uLightingOn;
 int uGlobalAmbient;
 int uLightsOn[8];
 int uLightsPos[8];
+int uLightsPosI[8];
 int uLightsDiffuse[8];
 int uLightsAmbient[8];
 int uLightsSpecular[8];
+int uPerVertexColor;
+int uMatDiffuse;
+int uMatAmbient;
+int uMatSpecular;
+int uMatEmissive;
+int uMatPower;
+int uMatOpacity;
+int uMatTwoSided;
 
 void shader_LoadMatrixf(MatrixMode mode, float * m)
 {
@@ -36,7 +45,7 @@ void shader_LoadMatrixf(MatrixMode mode, float * m)
 
 void shader_setGlobalAmbient(float r, float g, float b, float a)
 {
-   glUniform4f(uGlobalAmbient, r, g, b, a);
+   glUniform3f(uGlobalAmbient, r, g, b);
 }
 
 void shader_color(float r, float g, float b, float a)
@@ -54,6 +63,18 @@ void shader_texturing(bool on)
    glUniform1ui(uTexturingOn, on);
 }
 
+void shader_setMaterial(Material material, bool perVertexColor)
+{
+   glUniform1ui(uPerVertexColor, perVertexColor);
+   glUniform1ui(uMatTwoSided, !material.flags.singleSideLight);
+   glUniform3f(uMatDiffuse, material.diffuse.r, material.diffuse.g, material.diffuse.b);
+   glUniform3f(uMatAmbient, material.ambient.r, material.ambient.g, material.ambient.b);
+   glUniform3f(uMatSpecular, material.specular.r, material.specular.g, material.specular.b);
+   glUniform3f(uMatEmissive, material.emissive.r, material.emissive.g, material.emissive.b);
+   glUniform1f(uMatPower, material.power);
+   glUniform1f(uMatOpacity, material.opacity);
+}
+
 void shader_setLight(Display display, uint id, Light light)
 {
    if(light != null)
@@ -65,20 +86,20 @@ void shader_setLight(Display display, uint id, Light light)
 
       if(!multiplier) multiplier = 1.0f;
 
-      glUniform4f(uLightsDiffuse[id],
+      glUniform3f(uLightsDiffuse[id],
          light.diffuse.r * multiplier,
          light.diffuse.g * multiplier,
-         light.diffuse.b * multiplier, 1.0);
+         light.diffuse.b * multiplier);
 
-      glUniform4f(uLightsAmbient[id],
+      glUniform3f(uLightsAmbient[id],
          light.ambient.r * multiplier,
          light.ambient.g * multiplier,
-         light.ambient.b * multiplier, 1.0);
+         light.ambient.b * multiplier);
 
-      glUniform4f(uLightsSpecular[id],
+      glUniform3f(uLightsSpecular[id],
          light.specular.r * multiplier,
          light.specular.g * multiplier,
-         light.specular.b * multiplier, 1.0);
+         light.specular.b * multiplier);
 
       if(lightObject)
       {
@@ -144,19 +165,24 @@ void shader_setLight(Display display, uint id, Light light)
       }
       else
       {
-         Vector3Df l;
+         Vector3Df l, li;
          Vector3Df vector { 0,0,-1 };
-         Vector3Df direction;
+         Vector3Df vectorI { 0,0, 1 };
+         Vector3Df direction, directionI;
          Matrix mat;
 
          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;
+
+            li.Normalize(directionI);
+            li.z *= -1;
          }
          else
          {
@@ -165,8 +191,12 @@ void shader_setLight(Display display, uint id, Light light)
             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
@@ -277,6 +307,14 @@ void loadShaders(const String vertexShaderFile, const String fragmentShaderFile)
       uTexturingOn   = glGetUniformLocation(program, "texturingOn");
       uLightingOn    = glGetUniformLocation(program, "lightingOn");
       uGlobalAmbient = glGetUniformLocation(program, "globalAmbient");
+      uPerVertexColor  = glGetUniformLocation(program, "perVertexColor");
+      uMatDiffuse       = glGetUniformLocation(program, "matDiffuse");
+      uMatAmbient       = glGetUniformLocation(program, "matAmbient");
+      uMatSpecular      = glGetUniformLocation(program, "matSpecular");
+      uMatEmissive      = glGetUniformLocation(program, "matEmissive");
+      uMatPower         = glGetUniformLocation(program, "matPower");
+      uMatOpacity       = glGetUniformLocation(program, "matOpacity");
+      uMatTwoSided      = glGetUniformLocation(program, "matTwoSided");
 
       for(i = 0; i < 8; i++)
       {
@@ -288,6 +326,9 @@ 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);