Normal mapping gone horribly wrong

My bet is on the color setting/mixing in fragment shader…

  1. you are setting output color more then once

    If I remember correctly on some gfx drivers that do a big problems for example everything after the line

    color = vec4(brownColor * (texture(diffuseMap, fsCoords).rgb + 0.25), 1.0);//add a fixed base color (0.25), because its dark as hell
    

    could be deleted by driver …

  2. you are adding color and intensities instead of color*intensity

    but I could overlook someting.

  3. try just normal/bump shading at first

    Ignore ambient,reflect,specular… and then if it works add the rest one by one. Always check the shader’s compilation logs

Too lazy to further analyze your code, so here is how I do it:

bump mapping example

Left size is space ship object (similar to ZXS Elite’s Viper) rendered with fixed function. Right side the same (a bit different rotation of object) with GLSL shader’s in place and this normal/bump map

enter image description here

[Vertex]

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
// texture units:
// 0 - texture0 map 2D rgba
// 1 - texture1 map 2D rgba
// 2 - normal map 2D xyz
// 3 - specular map 2D i
// 4 - light map 2D rgb rgb
// 5 - enviroment/skybox cube map 3D rgb

uniform mat4x4 tm_l2g;
uniform mat4x4 tm_l2g_dir;
uniform mat4x4 tm_g2s;

uniform mat4x4 tm_l2s_per;
uniform mat4x4 tm_per;

layout(location=0) in vec3 pos;
layout(location=1) in vec4 col;
layout(location=2) in vec2 txr;
layout(location=3) in vec3 tan;
layout(location=4) in vec3 bin;
layout(location=5) in vec3 nor;

out smooth vec3 pixel_pos;
out smooth vec4 pixel_col;
out smooth vec2 pixel_txr;
//out flat   mat3 pixel_TBN;
out smooth mat3 pixel_TBN;
//------------------------------------------------------------------
void main(void)
    {
    vec4 p;
    p.xyz=pos;
    p.w=1.0;
    p=tm_l2g*p;
    pixel_pos=p.xyz;
    p=tm_g2s*p;
    gl_Position=p;
    pixel_col=col;
    pixel_txr=txr;
    p.xyz=tan.xyz; p.w=1.0; pixel_TBN[0]=normalize((tm_l2g_dir*p).xyz);
    p.xyz=bin.xyz; p.w=1.0; pixel_TBN[1]=normalize((tm_l2g_dir*p).xyz);
    p.xyz=nor.xyz; p.w=1.0; pixel_TBN[2]=normalize((tm_l2g_dir*p).xyz);
    }
//------------------------------------------------------------------

[Fragment]

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
in smooth vec3 pixel_pos;
in smooth vec4 pixel_col;
in smooth vec2 pixel_txr;
//in flat   mat3 pixel_TBN;
in smooth mat3 pixel_TBN;

uniform sampler2D   txr_texture0;
uniform sampler2D   txr_texture1;
uniform sampler2D   txr_normal;
uniform sampler2D   txr_specular;
uniform sampler2D   txr_light;
uniform samplerCube txr_skybox;

const int _lights=3;
uniform vec3 light_col0=vec3(0.1,0.1,0.1);
uniform vec3 light_dir[_lights]=         // direction to local star in ellipsoid space
    {
    vec3(0.0,0.0,+1.0),
    vec3(0.0,0.0,+1.0),
    vec3(0.0,0.0,+1.0),
    };
uniform vec3 light_col[_lights]=         // local star color * visual intensity
    {
    vec3(1.0,0.0,0.0),
    vec3(0.0,1.0,0.0),
    vec3(0.0,0.0,1.0),
    };

out layout(location=0) vec4 frag_col;

const vec4 v05=vec4(0.5,0.5,0.5,0.5);
const bool _blend=false;
const bool _reflect=true;
//------------------------------------------------------------------
void main(void)
    {
    float a=0.0,b,li;
    vec4 col,blend0,blend1,specul,skybox;
    vec3 normal;
    col=(texture2D(txr_normal,pixel_txr.st)-v05)*2.0;       // normal/bump maping
//  normal=pixel_TBN*col.xyz;
    normal=pixel_TBN[0];
    blend0=texture(txr_texture0,pixel_txr.st);
    blend1=texture(txr_texture1,pixel_txr.st);
    specul=texture(txr_specular,pixel_txr.st);
    skybox=texture(txr_skybox,normal);

    if (_blend)
        {
        a=blend1.a;
        blend0*=1.0-a;
        blend1*=a;
        blend0+=blend1;
        blend0.a=a;
        }

    col.xyz=light_col0; col.a=0.0; li=0.0;                          // normal shading (aj s bump mapingom)
    for (int i=0;i<_lights;i++)
            {
            b=dot(light_dir[i],normal.xyz);
            if (b<0.0) b=0.0;
//          b*=specul.r;
            li+=b;
            col.xyz+=light_col[i]*b;
            }
    col*=blend0;
    if (li<=0.1)
        {
        blend0=texture2D(txr_light,pixel_txr.st);
        blend0*=1.0-a;
        blend0.a=a;
        col+=blend0;
        }
    if (_reflect) col+=skybox*specul.r;
        col*=pixel_col;
    if (col.r<0.0) col.r=0.0;
    if (col.g<0.0) col.g=0.0;
    if (col.b<0.0) col.b=0.0;
    a=0.0;
    if (a<col.r) a=col.r;
    if (a<col.g) a=col.g;
    if (a<col.b) a=col.b;
    if (a>1.0)
        {
        a=1.0/a;
        col.r*=a;
        col.g*=a;
        col.b*=a;
        }
    frag_col=col;
    }
//------------------------------------------------------------------

These source codes are bit old and mix of different things for specific application

So extract only what you need from it. If you are confused with the variable names then comment me…

  • tm_ stands for transform matrix
  • l2g stands for local coordinate system to global coordinate system transform
  • dir means that transformation changes just direction (offset is 0,0,0)
  • g2s stands for global to screen …
  • per is perspective transform …

The GLSL compilation log

You have to obtain its content programaticaly after compilation of your shader’s (not application!!!). I do it with calling the function glGetShaderInfoLog for every shader,program I use …

[Notes]

Some drivers optimize “unused” variables. As you can see at the image txr_texture1 is not found even if the fragment shader has it in code but the blending is not used in this App so driver deleted it on its own…

Shader logs can show you much (syntax errors, warnings…)

there are few GLSL IDEs for making shader’s easy but I prefer my own because I can use in it the target app code directly. Mine looks like this:

GLSL IDE

each txt window is a shader source (vertex,fragment,…) the right bottom is clipboard, left top is shader’s log after last compilation and left bottom is the preview. I managed to code it like Borland style IDE (with the keys also and syntax highlight) the other IDEs I saw look similar (different colors of coarse:)) anyway if you want to play with shader’s download such App or do it your self it will help a lot…

There could be also a problem with TBN creation

You should visually check if the TBN vectors (tangent,binormal,normal) correspond to object surface by drawing colored lines at each vertex position. Just to be sure… something like this:

normals

Leave a Comment