Normal mapping and lighting gone wrong, not displaying correctly
I'm working on an implementation of normal mapping, calculating the
tangent vectors in the vertex shader.
The normal mapping seems to work perfectly on objects that have a model
matrix close to the identity matrix. As long as I start translating and
scaling, my lighting seems off. As you can see in the picture the normal
mapping works perfectly on the container cube, but the lighting fails on
the large floor (direction of the specular light should be towards the
player, not towards the container).
I get the feeling it somehow has something to do with the position of the
light (currently traversing from x = -10 to x = 10 over time) not properly
being included in the calculations as long as I start changing the model
matrix (via translations/scaling). I'm posting all the relevant code and
hope you guys can somehow see something I'm missing since I've been
staring at my code for days.
Vertex shader
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texture;
// fragment pass through
out vec2 Texture;
out vec3 Position;
out vec3 TangentSurface2Light;
out vec3 TangentSurface2View;
uniform vec3 lightPos;
// vertex transformation
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
mat3 normalMatrix = transpose(mat3(inverse(view * model)));
Texture = texture;
Position = vec3((view * model) * vec4(position, 1.0));
gl_Position = projection * view * model * vec4(position, 1.0);
// calculate tangent vector
vec3 light = vec3(view * vec4(lightPos, 1.0));
vec3 tangent;
vec3 v1 = cross(normal, vec3(0.0, 0.0, 1.0));
vec3 v2 = cross(normal, vec3(0.0, 1.0, 0.0));
if(length(v1) > length(v2))
tangent = v1;
else
tangent = v2;
vec3 n = normalize(normalMatrix * normal);
vec3 t = normalize(normalMatrix * tangent);
vec3 b = cross(n, t);
// create matrix for tangent (from vertex to tangent-space)
mat3 mat = mat3(t.x, b.x ,n.x, t.y, b.y ,n.y, t.z, b.z ,n.z);
vec3 vector = normalize(light - Position);
TangentSurface2Light = mat * vector;
vector = normalize(-Position);
TangentSurface2View = mat * vector;
}
Fragment shader
#version 330
in vec2 Texture;
in vec3 Position;
in vec3 TangentSurface2Light;
in vec3 TangentSurface2View;
out vec4 outColor;
uniform mat4 model;
uniform mat4 view;
uniform vec3 playerPos;
uniform vec3 lightPos;
uniform sampler2D img;
uniform sampler2D normalMap;
uniform float repeatFactor;
void main()
{
vec3 light = vec3(view * vec4(lightPos, 1.0));
float dist = length(light - Position);
// float att = 1.0 / (1.0 + 0.01 * dist + 0.001 * dist * dist);
float att = 1.0;
// Ambient
vec4 ambient = vec4(0.05);
// Diffuse
vec3 surface2light = normalize(TangentSurface2Light);
vec3 norm = normalize(texture(normalMap, Texture * repeatFactor).xyz *
2.0 - 1.0);
float contribution = max(dot(norm, surface2light), 0.0); // moet hier
even anders
// vec4 diffuse = contribution * vec4(0.4);
vec4 diffuse = contribution * vec4(0.6);
// Specular
vec3 surf2view = normalize(TangentSurface2View); // Player is always
at position 0
vec3 reflection = reflect(-surface2light, norm); // reflection vector
float specContribution = pow(max(dot(surf2view, reflection), 0.0), 32);
vec4 specular = vec4(0.7) * specContribution;
outColor = (ambient + diffuse + specular ) * texture(img, Texture *
repeatFactor);
}
OpenGL Drawing Code
void Render()
{
...
glm::mat4 view, projection; // Model will be done via MatrixStack
view = glm::lookAt(position, position + direction, up); // cam pos,
look at (eye pos), up vec
projection = glm::perspective(45.0f, (float)width/(float)height, 0.1f,
1000.0f);
glUniformMatrix4fv(glGetUniformLocation(basicShader.shaderProgram,
"view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(basicShader.shaderProgram,
"projection"), 1, GL_FALSE, glm::value_ptr(projection));
// Lighting
lightPos.x = 0.0 + sin(time / 125) * 10;
glUniform3f(glGetUniformLocation(basicShader.shaderProgram,
"lightPos"), lightPos.x, lightPos.y, lightPos.z);
// Objects (use bump mapping on this cube)
bumpShader.Use();
glUniformMatrix4fv(glGetUniformLocation(bumpShader.shaderProgram,
"view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(bumpShader.shaderProgram,
"projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniform3f(glGetUniformLocation(bumpShader.shaderProgram,
"lightPos"), lightPos.x, lightPos.y, lightPos.z);
MatrixStack::LoadIdentity();
MatrixStack::Scale(2);
MatrixStack::ToShader(glGetUniformLocation(bumpShader.shaderProgram,
"model"));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, resources.GetTexture("container"));
glUniform1i(glGetUniformLocation(bumpShader.shaderProgram, "img"), 0);
glActiveTexture(GL_TEXTURE1); // Normal map
glBindTexture(GL_TEXTURE_2D, resources.GetTexture("container_normal"));
glUniform1i(glGetUniformLocation(bumpShader.shaderProgram,
"normalMap"), 1);
glUniform1f(glGetUniformLocation(bumpShader.shaderProgram,
"repeatFactor"), 1);
cubeNormal.Draw();
MatrixStack::LoadIdentity();
MatrixStack::Translate(glm::vec3(0.0f, -22.0f, 0.0f));
MatrixStack::Scale(glm::vec3(200.0f, 20.0f, 200.0f));
MatrixStack::ToShader(glGetUniformLocation(bumpShader.shaderProgram,
"model"));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, resources.GetTexture("floor"));
glActiveTexture(GL_TEXTURE1); // Normal map
glBindTexture(GL_TEXTURE_2D, resources.GetTexture("floor_normal"));
glUniform1f(glGetUniformLocation(bumpShader.shaderProgram,
"repeatFactor"), 100);
cubeNormal.Draw();
MatrixStack::LoadIdentity();
glActiveTexture(GL_TEXTURE0);
...
}
No comments:
Post a Comment