diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp index 41660578..970a8788 100644 --- a/src/graphics/opengl/gl21device.cpp +++ b/src/graphics/opengl/gl21device.cpp @@ -388,6 +388,7 @@ bool CGL21Device::Create() uni.modelMatrix = glGetUniformLocation(m_normalProgram, "uni_ModelMatrix"); uni.normalMatrix = glGetUniformLocation(m_normalProgram, "uni_NormalMatrix"); uni.shadowMatrix = glGetUniformLocation(m_normalProgram, "uni_ShadowMatrix"); + uni.cameraPosition = glGetUniformLocation(m_normalProgram, "uni_CameraPosition"); uni.primaryTexture = glGetUniformLocation(m_normalProgram, "uni_PrimaryTexture"); uni.secondaryTexture = glGetUniformLocation(m_normalProgram, "uni_SecondaryTexture"); @@ -441,6 +442,7 @@ bool CGL21Device::Create() glUniformMatrix4fv(uni.modelMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni.normalMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni.shadowMatrix, 1, GL_FALSE, matrix.Array()); + glUniform3f(uni.cameraPosition, 0.0f, 0.0f, 0.0f); glUniform1i(uni.primaryTexture, 0); glUniform1i(uni.secondaryTexture, 1); @@ -653,6 +655,7 @@ void CGL21Device::SetTransform(TransformType type, const Math::Matrix &matrix) else if (type == TRANSFORM_VIEW) { Math::Matrix scale; + Math::Vector cameraPosition; scale.Set(3, 3, -1.0f); m_viewMat = Math::MultiplyMatrices(scale, matrix); @@ -660,6 +663,12 @@ void CGL21Device::SetTransform(TransformType type, const Math::Matrix &matrix) m_combinedMatrix = Math::MultiplyMatrices(m_projectionMat, m_modelviewMat); glUniformMatrix4fv(m_uniforms[m_mode].viewMatrix, 1, GL_FALSE, m_viewMat.Array()); + + if (m_uniforms[m_mode].cameraPosition >= 0) { + cameraPosition.LoadZero(); + cameraPosition = MatrixVectorMultiply(m_viewMat.Inverse(), cameraPosition); + glUniform3fv(m_uniforms[m_mode].cameraPosition, 1, cameraPosition.Array()); + } } else if (type == TRANSFORM_PROJECTION) { diff --git a/src/graphics/opengl/glutil.h b/src/graphics/opengl/glutil.h index 977bc9c3..b47d7300 100644 --- a/src/graphics/opengl/glutil.h +++ b/src/graphics/opengl/glutil.h @@ -167,6 +167,8 @@ struct UniformLocations GLint shadowMatrix = -1; //! Normal matrix GLint normalMatrix = -1; + //! Camera position + GLint cameraPosition = -1; //! Primary texture sampler GLint primaryTexture = -1; diff --git a/src/graphics/opengl/shaders/gl21/fs_normal.glsl b/src/graphics/opengl/shaders/gl21/fs_normal.glsl index d21bc9cf..3cefb8e6 100644 --- a/src/graphics/opengl/shaders/gl21/fs_normal.glsl +++ b/src/graphics/opengl/shaders/gl21/fs_normal.glsl @@ -56,6 +56,7 @@ uniform Material uni_Material; uniform int uni_LightCount; uniform LightParams uni_Light[4]; +varying vec3 pass_CameraDirection; varying float pass_Distance; varying vec4 pass_Color; varying vec3 pass_Normal; @@ -76,16 +77,17 @@ void main() vec4 specular = vec4(0.0f); vec3 normal = normalize(pass_Normal); + vec3 camera = normalize(pass_CameraDirection); for (int i = 0; i < uni_LightCount; i++) { LightParams light = uni_Light[i]; - vec3 lightDirection = light.Position.xyz; - vec3 reflectDirection = -reflect(lightDirection, normal); + vec3 lightDirection = normalize(light.Position.xyz); + vec3 reflectAxis = normalize(lightDirection + camera); float diffuseComponent = clamp(dot(normal, lightDirection), 0.0f, 1.0f); - float specularComponent = clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f); + float specularComponent = pow(clamp(dot(normal, reflectAxis), 0.0f, 1.0f), 10.0f); ambient += light.Ambient; diffuse += diffuseComponent * light.Diffuse; diff --git a/src/graphics/opengl/shaders/gl21/vs_normal.glsl b/src/graphics/opengl/shaders/gl21/vs_normal.glsl index 9195cd20..41141c4b 100644 --- a/src/graphics/opengl/shaders/gl21/vs_normal.glsl +++ b/src/graphics/opengl/shaders/gl21/vs_normal.glsl @@ -24,7 +24,9 @@ uniform mat4 uni_ViewMatrix; uniform mat4 uni_ModelMatrix; uniform mat4 uni_ShadowMatrix; uniform mat4 uni_NormalMatrix; +uniform vec3 uni_CameraPosition; +varying vec3 pass_CameraDirection; varying float pass_Distance; varying vec4 pass_Color; varying vec3 pass_Normal; @@ -40,6 +42,7 @@ void main() gl_Position = uni_ProjectionMatrix * eyeSpace; + pass_CameraDirection = uni_CameraPosition - position.xyz; pass_Color = gl_Color; pass_Normal = normalize((uni_NormalMatrix * vec4(gl_Normal, 0.0f)).xyz); pass_Distance = abs(eyeSpace.z / eyeSpace.w);