Rewritten lighting in OpenGL 2.1 engine

dev-time-step
Tomasz Kapuściński 2016-02-10 23:38:49 +01:00
parent 898001e065
commit 32b480b226
5 changed files with 153 additions and 97 deletions

View File

@ -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()));
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);
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);
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.

View File

@ -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];
};

View File

@ -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);
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;
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)

View File

@ -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)

View File

@ -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;
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);
gl_FrontColor = color;
gl_FrontColor = vec4(min(vec3(1.0f), result.rgb), 1.0f);
}
}