c++ - Normal mapping and lighting gone wrong, not displaying correctly -


i'm working on implementation of normal mapping, calculating tangent vectors via assimp library.

the normal mapping seems work on objects have model matrix close identity matrix. long start translating , scaling, lighting seems off. can see in picture normal mapping works on container cube, lighting fails on large floor (direction of specular light should towards player, not towards container).

lighting not working on normal mapping

i feeling somehow has position of light (currently traversing x = -10 x = 10 on time) not being included in calculations long start changing model matrix (via translations/scaling). i'm posting relevant code , hope guys can somehow see i'm missing since i've been staring @ code days.

vertex shader

#version 330  layout(location = 0) in vec3 position; layout(location = 1) in vec3 normal; layout(location = 2) in vec3 tangent; layout(location = 3) in vec3 color; layout(location = 4) in vec2 texcoord;  // fragment pass through out vec3 position; out vec3 normal; out vec3 tangent; out vec3 color; out vec2 texcoord;  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)));      position = vec3((view * model) * vec4(position, 1.0));      normal = normalmatrix * normal;     tangent = tangent;     color = color;     texcoord = texcoord;      gl_position = projection * view * model * vec4(position, 1.0);      vec3 light = vec3(view * vec4(lightpos, 1.0));     vec3 n = normalize(normalmatrix * normal);     vec3 t = normalize(normalmatrix * tangent);     vec3 b = cross(n, t);     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 vec3 position; in vec3 normal; in vec3 tangent; in vec3 color; in vec2 texcoord;  in vec3 tangentsurface2light; in vec3 tangentsurface2view;  out vec4 outcolor;  uniform vec3 lightpos; uniform mat4 view; uniform sampler2d texture0; uniform sampler2d texture_normal; // normal  uniform float repeatfactor = 1;  void main() {        vec4 texcolor = texture(texture0, texcoord * repeatfactor);     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);     // ambient     vec4 ambient = vec4(0.2);     // diffuse     vec3 surface2light = normalize(tangentsurface2light);     vec3 norm = normalize(texture(texture_normal, texcoord * repeatfactor).xyz * 2.0 - 1.0);      float contribution = max(dot(norm, surface2light), 0.0);     vec4 diffuse = contribution * vec4(0.8);     // specular     vec3 surf2view = normalize(tangentsurface2view);     vec3 reflection = reflect(-surface2light, norm); // reflection vector     float speccontribution = pow(max(dot(surf2view, reflection), 0.0), 32);     vec4 specular = vec4(0.6) * speccontribution;      outcolor = (ambient + (diffuse * att)+ (specular * pow(att, 3))) * texcolor; } 

opengl drawing code

void render() {     ...      glm::mat4 view, projection; // model done via matrixstack     view = glm::lookat(position, position + direction, up); // cam pos, @ (eye pos), 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 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);      ... } 

edit loaded objects using assimp library 'aiprocess_calctangentspace' flag enabled , changed shaders accordingly adapt new changes. since assimp automatically calculates correct tangent vectors should have valid tangent vectors , problem should solved (as noted nicol bolas), still have same issue specular lighting acting strange , diffuse lighting not showing up. guess there still else not working correctly. unmarked answer correct answer nicol bolas (for now) , updated code accordingly since there still i'm missing.

it has translating. add translate (-22.0f in y direction) model matrix reacts strange lighting. long floor (which cube) has no translation lighting looks fine.

calculating tangent vectors in vertex shader

well there's problem. that's not possible arbitrary surface.

the tangent , bitangent not arbitrary vectors perpendicular 1 another. model-space direction vectors point in direction of texture coordinates. tangent points in direction of s texture coordinate, , bitangent points in direction of t texture coordinate (or u , v tex coords, if prefer).

this computes orientation of texture relative each vertex on surface. need orientation, because way texture mapped surface matters when want make sense of tangent-space vector.

remember: tangent-space space perpendicular surface. need know how surface mapped object in order know "up" is, example. take square surface. map texture +y part of square oriented along +t direction of texture. or along +x of square. map texture distorted, or rotated @ arbitrary angle.

the tangent , bitangent vectors intended correct mapping. point in s , t directions in model space. so, combined normal, form transformation matrix transform tangent-space whatever space 3 vectors in (you transform nbt camera space or whatever space use lighting before using them).

you cannot compute them taking normal , crossing arbitrary vector. produces perpendicular normal, not right one.

in order correctly compute tangent/bitangent, need access more 1 vertex. need able see how texture coordinates change on surface of mesh, how compute s , t directions relative mesh.

vertex shaders cannot access more 1 vertex. geometry shaders can't (generally) access enough vertices either. compute tangent/bitangent off-line on cpu.


Comments

Popular posts from this blog

matlab - Deleting rows with specific rules -

php - MySQLi multi_query results for later use -