[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