[colobot] 257/377: Rewritten lighting in OpenGL 2.1 engine

Didier Raboud odyx at moszumanska.debian.org
Wed Mar 30 13:34:24 UTC 2016


This is an automated email from the git hooks/post-receive script.

odyx pushed a commit to branch debian/master
in repository colobot.

commit 32b480b2264c353f7554cfd50733b6880fcdf5cc
Author: Tomasz Kapuściński <tomaszkax86 at gmail.com>
Date:   Wed Feb 10 23:38:49 2016 +0100

    Rewritten lighting in OpenGL 2.1 engine
---
 src/graphics/opengl/gl21device.cpp                 | 88 ++++++++++++----------
 src/graphics/opengl/gl21device.h                   | 28 ++++++-
 .../shaders/fragment_shader_21_perpixel.glsl       | 65 +++++++++-------
 .../shaders/fragment_shader_21_pervertex.glsl      |  5 +-
 .../opengl/shaders/vertex_shader_21_pervertex.glsl | 64 +++++++++-------
 5 files changed, 153 insertions(+), 97 deletions(-)

diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp
index cf10607..8a4fcd9 100644
--- a/src/graphics/opengl/gl21device.cpp
+++ b/src/graphics/opengl/gl21device.cpp
@@ -273,7 +273,11 @@ bool CGL21Device::Create()
         sprintf(filename, "shaders/vertex_shader_21_pervertex.glsl");
 
     shaders[0] = LoadShader(GL_VERTEX_SHADER, filename);
-    if (shaders[0] == 0) return false;
+    if (shaders[0] == 0)
+    {
+        m_errorMessage = GetLastShaderError();
+        return false;
+    }
 
     if (m_perPixelLighting)
         sprintf(filename, "shaders/fragment_shader_21_perpixel.glsl");
@@ -281,10 +285,18 @@ bool CGL21Device::Create()
         sprintf(filename, "shaders/fragment_shader_21_pervertex.glsl");
 
     shaders[1] = LoadShader(GL_FRAGMENT_SHADER, filename);
-    if (shaders[1] == 0) return false;
+    if (shaders[1] == 0)
+    {
+        m_errorMessage = GetLastShaderError();
+        return false;
+    }
 
     m_program = LinkProgram(2, shaders);
-    if (m_program == 0) return false;
+    if (m_program == 0)
+    {
+        m_errorMessage = GetLastShaderError();
+        return false;
+    }
 
     glDeleteShader(shaders[0]);
     glDeleteShader(shaders[1]);
@@ -318,11 +330,30 @@ bool CGL21Device::Create()
     uni_ShadowColor = glGetUniformLocation(m_program, "uni_ShadowColor");
     uni_LightingEnabled = glGetUniformLocation(m_program, "uni_LightingEnabled");
 
+    uni_AmbientColor = glGetUniformLocation(m_program, "uni_AmbientColor");
+    uni_DiffuseColor = glGetUniformLocation(m_program, "uni_DiffuseColor");
+    uni_SpecularColor = glGetUniformLocation(m_program, "uni_SpecularColor");
+
+    GLchar name[64];
     for (int i = 0; i < 8; i++)
     {
-        char name[64];
-        sprintf(name, "uni_LightEnabled[%d]", i);
-        uni_LightEnabled[i] = glGetUniformLocation(m_program, name);
+        sprintf(name, "uni_Light[%d].Enabled", i);
+        uni_Light[i].Enabled = glGetUniformLocation(m_program, name);
+
+        sprintf(name, "uni_Light[%d].Position", i);
+        uni_Light[i].Position = glGetUniformLocation(m_program, name);
+
+        sprintf(name, "uni_Light[%d].Ambient", i);
+        uni_Light[i].Ambient = glGetUniformLocation(m_program, name);
+
+        sprintf(name, "uni_Light[%d].Diffuse", i);
+        uni_Light[i].Diffuse = glGetUniformLocation(m_program, name);
+
+        sprintf(name, "uni_Light[%d].Specular", i);
+        uni_Light[i].Specular = glGetUniformLocation(m_program, name);
+
+        sprintf(name, "uni_Light[%d].Attenuation", i);
+        uni_Light[i].Attenuation = glGetUniformLocation(m_program, name);
     }
 
     // Set default uniform values
@@ -355,7 +386,7 @@ bool CGL21Device::Create()
 
     glUniform1i(uni_LightingEnabled, 0);
     for (int i = 0; i < 8; i++)
-        glUniform1i(uni_LightEnabled[i], 0);
+        glUniform1i(uni_Light[i].Enabled, 0);
 
     // create default framebuffer object
     FramebufferParams framebufferParams;
@@ -485,9 +516,9 @@ void CGL21Device::SetMaterial(const Material &material)
 {
     m_material = material;
 
-    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,  m_material.ambient.Array());
-    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_material.diffuse.Array());
-    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_material.specular.Array());
+    glUniform4fv(uni_AmbientColor, 1, m_material.ambient.Array());
+    glUniform4fv(uni_DiffuseColor, 1, m_material.diffuse.Array());
+    glUniform4fv(uni_SpecularColor, 1, m_material.specular.Array());
 }
 
 int CGL21Device::GetMaxLightCount()
@@ -502,40 +533,21 @@ void CGL21Device::SetLight(int index, const Light &light)
 
     m_lights[index] = light;
 
-    // Indexing from GL_LIGHT0 should always work
-    glLightfv(GL_LIGHT0 + index, GL_AMBIENT,  const_cast<GLfloat*>(light.ambient.Array()));
-    glLightfv(GL_LIGHT0 + index, GL_DIFFUSE,  const_cast<GLfloat*>(light.diffuse.Array()));
-    glLightfv(GL_LIGHT0 + index, GL_SPECULAR, const_cast<GLfloat*>(light.specular.Array()));
-
-    glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION,  light.attenuation0);
-    glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION,    light.attenuation1);
-    glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, light.attenuation2);
+    glUniform4fv(uni_Light[index].Ambient, 1, light.ambient.Array());
+    glUniform4fv(uni_Light[index].Diffuse, 1, light.diffuse.Array());
+    glUniform4fv(uni_Light[index].Specular, 1, light.specular.Array());
+    glUniform3f(uni_Light[index].Attenuation, light.attenuation0, light.attenuation1, light.attenuation2);
 
-    if (light.type == LIGHT_SPOT)
+    if (light.type == LIGHT_DIRECTIONAL)
     {
-        glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle * Math::RAD_TO_DEG);
-        glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, light.spotIntensity);
+        glUniform4f(uni_Light[index].Position, -light.direction.x, -light.direction.y, -light.direction.z, 0.0f);
     }
     else
     {
-        glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
+        glUniform4f(uni_Light[index].Position, light.position.x, light.position.y, light.position.z, 1.0f);
     }
 
-    if (light.type == LIGHT_SPOT)
-    {
-        GLfloat direction[4] = { -light.direction.x, -light.direction.y, -light.direction.z, 1.0f };
-        glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction);
-    }
-    else if (light.type == LIGHT_DIRECTIONAL)
-    {
-        GLfloat position[4] = { -light.direction.x, -light.direction.y, -light.direction.z, 0.0f };
-        glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
-    }
-    else
-    {
-        GLfloat position[4] = { light.position.x, light.position.y, light.position.z, 1.0f };
-        glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
-    }
+    // TODO: add spotlight params
 }
 
 void CGL21Device::SetLightEnabled(int index, bool enabled)
@@ -545,7 +557,7 @@ void CGL21Device::SetLightEnabled(int index, bool enabled)
 
     m_lightsEnabled[index] = enabled;
 
-    glUniform1i(uni_LightEnabled[index], enabled ? 1 : 0);
+    glUniform1i(uni_Light[index].Enabled, enabled ? 1 : 0);
 }
 
 /** If image is invalid, returns invalid texture.
diff --git a/src/graphics/opengl/gl21device.h b/src/graphics/opengl/gl21device.h
index 5be94a5..f2b3bc4 100644
--- a/src/graphics/opengl/gl21device.h
+++ b/src/graphics/opengl/gl21device.h
@@ -299,8 +299,32 @@ private:
 
     //! true enables lighting
     GLint uni_LightingEnabled = 0;
-    //! true enables light source
-    GLint uni_LightEnabled[8] = {};
+    //! Ambient color
+    GLint uni_AmbientColor = 0;
+    //! Diffuse color
+    GLint uni_DiffuseColor = 0;
+    //! Specular color
+    GLint uni_SpecularColor = 0;
+
+    struct LightUniforms
+    {
+        //! true enables light
+        GLint Enabled = 0;
+        //! Light type
+        GLint Type = 0;
+        //! Position or direction vector
+        GLint Position = 0;
+        //! Ambient color
+        GLint Ambient = 0;
+        //! Diffuse color
+        GLint Diffuse = 0;
+        //! Specular color
+        GLint Specular = 0;
+        //! Attenuation
+        GLint Attenuation = 0;
+    };
+
+    LightUniforms uni_Light[8];
 };
 
 
diff --git a/src/graphics/opengl/shaders/fragment_shader_21_perpixel.glsl b/src/graphics/opengl/shaders/fragment_shader_21_perpixel.glsl
index 8f1213a..723fe05 100644
--- a/src/graphics/opengl/shaders/fragment_shader_21_perpixel.glsl
+++ b/src/graphics/opengl/shaders/fragment_shader_21_perpixel.glsl
@@ -34,8 +34,23 @@ uniform vec4 uni_FogColor;
 
 uniform float uni_ShadowColor;
 
+struct LightParams
+{
+    bool Enabled;
+    vec4 Position;
+    vec4 Ambient;
+    vec4 Diffuse;
+    vec4 Specular;
+    float Shininess;
+    vec3 Attenuation;
+};
+
+uniform vec4 uni_AmbientColor;
+uniform vec4 uni_DiffuseColor;
+uniform vec4 uni_SpecularColor;
+
 uniform bool uni_LightingEnabled;
-uniform bool uni_LightEnabled[8];
+uniform LightParams uni_Light[8];
 
 varying vec3 pass_Normal;
 varying vec3 pass_Position;
@@ -51,46 +66,41 @@ void main()
         vec4 diffuse = vec4(0.0f);
         vec4 specular = vec4(0.0f);
 
-        vec3 normal = pass_Normal;
+        vec3 normal = (gl_FrontFacing ? pass_Normal : -pass_Normal);
 
-        for(int i=0; i<8; i++)
+        for (int i = 0; i < 8; i++)
         {
-            if(uni_LightEnabled[i])
+            if (uni_Light[i].Enabled)
             {
-                vec3 lightDirection = vec3(0.0f);
-                float atten;
+                vec3 lightDirection = uni_Light[i].Position.xyz;
+                float atten = 1.0f;
 
-                // Directional light
-                if(gl_LightSource[i].position.w == 0.0f)
-                {
-                    lightDirection = gl_LightSource[i].position.xyz;
-                    atten = 1.0f;
-                }
                 // Point light
-                else
+                if (abs(uni_Light[i].Position.w) > 1e-3f)
                 {
-                    vec3 lightDirection = normalize(gl_LightSource[i].position.xyz - pass_Position);
-                    float dist = distance(gl_LightSource[i].position.xyz, pass_Position);
+                    vec3 lightDirection = normalize(uni_Light[i].Position.xyz - pass_Position.xyz);
+                    float dist = distance(uni_Light[i].Position.xyz, pass_Position.xyz);
+
+                    vec3 lightAtten = uni_Light[i].Attenuation;
 
-                    atten = 1.0f / (gl_LightSource[i].constantAttenuation
-                            + gl_LightSource[i].linearAttenuation * dist
-                            + gl_LightSource[i].quadraticAttenuation * dist * dist);
+                    atten = 1.0f / (lightAtten.x
+                            + lightAtten.y * dist
+                            + lightAtten.z * dist * dist);
                 }
 
                 vec3 reflectDirection = -reflect(lightDirection, normal);
 
-                ambient += gl_LightSource[i].ambient;
-                diffuse += atten * clamp(dot(normal, lightDirection), 0.0f, 1.0f) * gl_LightSource[i].diffuse;
-                specular += atten * clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f) * gl_LightSource[i].specular;
+                ambient += uni_Light[i].Ambient;
+                diffuse += atten * clamp(dot(normal, lightDirection), 0.0f, 1.0f) * uni_Light[i].Diffuse;
+                specular += atten * clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f) * uni_Light[i].Specular;
             }
         }
 
-        vec4 result = gl_FrontMaterial.ambient * ambient
-                + gl_FrontMaterial.diffuse * diffuse
-                + gl_FrontMaterial.specular * specular;
+        vec4 result = uni_AmbientColor * ambient
+                + uni_DiffuseColor * diffuse
+                + uni_SpecularColor * specular;
 
-        color.rgb = min(vec3(1.0f), result.rgb);
-        color.a = 1.0f; //min(1.0f, 1.0f);
+        color = vec4(min(vec3(1.0f), result.rgb), 1.0f);
     }
 
     if (uni_TextureEnabled[0])
@@ -105,7 +115,8 @@ void main()
 
     if (uni_TextureEnabled[2])
     {
-        color = color * mix(uni_ShadowColor, 1.0f, shadow2D(uni_ShadowTexture, gl_TexCoord[2].xyz).x);
+        if (gl_FrontFacing)
+            color.rgb *= mix(uni_ShadowColor, 1.0f, shadow2D(uni_ShadowTexture, gl_TexCoord[2].xyz).x);
     }
 
     if (uni_FogEnabled)
diff --git a/src/graphics/opengl/shaders/fragment_shader_21_pervertex.glsl b/src/graphics/opengl/shaders/fragment_shader_21_pervertex.glsl
index 340fa86..7d96555 100644
--- a/src/graphics/opengl/shaders/fragment_shader_21_pervertex.glsl
+++ b/src/graphics/opengl/shaders/fragment_shader_21_pervertex.glsl
@@ -52,7 +52,10 @@ void main()
 
     if (uni_TextureEnabled[2])
     {
-        color = color * mix(uni_ShadowColor, 1.0f, shadow2D(uni_ShadowTexture, gl_TexCoord[2].xyz).x);
+        if (gl_FrontFacing)
+            color.rgb *= mix(uni_ShadowColor, 1.0f, shadow2D(uni_ShadowTexture, gl_TexCoord[2].xyz).x);
+        else
+            color.rgb *= uni_ShadowColor;
     }
 
     if (uni_FogEnabled)
diff --git a/src/graphics/opengl/shaders/vertex_shader_21_pervertex.glsl b/src/graphics/opengl/shaders/vertex_shader_21_pervertex.glsl
index eee0c1e..e2b9315 100644
--- a/src/graphics/opengl/shaders/vertex_shader_21_pervertex.glsl
+++ b/src/graphics/opengl/shaders/vertex_shader_21_pervertex.glsl
@@ -25,8 +25,23 @@ uniform mat4 uni_ModelMatrix;
 uniform mat4 uni_ShadowMatrix;
 uniform mat4 uni_NormalMatrix;
 
+struct LightParams
+{
+    bool Enabled;
+    vec4 Position;
+    vec4 Ambient;
+    vec4 Diffuse;
+    vec4 Specular;
+    float Shininess;
+    vec3 Attenuation;
+};
+
+uniform vec4 uni_AmbientColor;
+uniform vec4 uni_DiffuseColor;
+uniform vec4 uni_SpecularColor;
+
 uniform bool uni_LightingEnabled;
-uniform bool uni_LightEnabled[8];
+uniform LightParams uni_Light[8];
 
 varying float pass_Distance;
 
@@ -44,53 +59,44 @@ void main()
 
     if (uni_LightingEnabled)
     {
-        vec4 color;
         vec4 ambient = vec4(0.0f);
         vec4 diffuse = vec4(0.0f);
         vec4 specular = vec4(0.0f);
 
         vec3 normal = normalize((uni_NormalMatrix * vec4(gl_Normal, 0.0f)).xyz);
 
-        for(int i=0; i<8; i++)
+        for (int i = 0; i < 8; i++)
         {
-            if(uni_LightEnabled[i])
+            if (uni_Light[i].Enabled)
             {
-                vec3 lightDirection = vec3(0.0f);
-                float atten;
+                vec3 lightDirection = uni_Light[i].Position.xyz;
+                float atten = 1.0f;
 
-                // Directional light
-                if(gl_LightSource[i].position.w == 0.0f)
-                {
-                    lightDirection = gl_LightSource[i].position.xyz;
-                    atten = 1.0f;
-                }
                 // Point light
-                else
+                if (abs(uni_Light[i].Position.w) > 1e-3f)
                 {
-                    vec3 lightDirection = normalize(gl_LightSource[i].position.xyz - position.xyz);
-                    float dist = distance(gl_LightSource[i].position.xyz, position.xyz);
+                    vec3 lightDirection = normalize(uni_Light[i].Position.xyz - position.xyz);
+                    float dist = distance(uni_Light[i].Position.xyz, position.xyz);
 
-                    atten = 1.0f / (gl_LightSource[i].constantAttenuation
-                            + gl_LightSource[i].linearAttenuation * dist
-                            + gl_LightSource[i].quadraticAttenuation * dist * dist);
+                    vec3 lightAtten = uni_Light[i].Attenuation;
+
+                    atten = 1.0f / (lightAtten.x
+                            + lightAtten.y * dist
+                            + lightAtten.z * dist * dist);
                 }
 
                 vec3 reflectDirection = -reflect(lightDirection, normal);
 
-                ambient += gl_LightSource[i].ambient;
-                diffuse += atten * clamp(dot(normal, lightDirection), 0.0f, 1.0f) * gl_LightSource[i].diffuse;
-                specular += atten * clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f) * gl_LightSource[i].specular;
+                ambient += uni_Light[i].Ambient;
+                diffuse += atten * clamp(dot(normal, lightDirection), 0.0f, 1.0f) * uni_Light[i].Diffuse;
+                specular += atten * clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f) * uni_Light[i].Specular;
             }
         }
 
-        vec4 result = gl_FrontMaterial.ambient * ambient
-                + gl_FrontMaterial.diffuse * diffuse
-                + gl_FrontMaterial.specular * specular;
-
-        color.rgb = min(vec3(1.0f), result.rgb);
-        color.a = 1.0f; //min(1.0f, 1.0f);
+        vec4 result = uni_AmbientColor * ambient
+                + uni_DiffuseColor * diffuse
+                + uni_SpecularColor * specular;
 
-        gl_FrontColor = color;
+        gl_FrontColor = vec4(min(vec3(1.0f), result.rgb), 1.0f);
     }
 }
-

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git



More information about the Pkg-games-commits mailing list