Bump mapping not working / How to Debug GLSL

Ok, it used to be a simple bump mapping technique. At least in theory.

First, we go with the tangents. They seem to be right as you can see below:

Second, we pass them and set the textures uniforms:


                shader->useProgram(BUMP);
                GLuint tangentLoc= glGetAttribLocation (shader->handle_shader_programs[BUMP], "tangent");
                glEnableVertexAttribArray (tangentLoc);
                glVertexAttribPointer(tangentLoc, 3, GL_FLOAT, GL_FALSE, 0, tangent_array);

                GLuint loc= glGetUniformLocationARB(shader->handle_shader_programs[BUMP],"diffuse_map");
                glUniform1iARB( loc ,0);
                loc= glGetUniformLocationARB(shader->handle_shader_programs[BUMP],"normal_map");
                glUniform1iARB(loc,1);


I am not posting the render code here, but I am sure both of the textures are being send to the shader with:

                                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTexture(GL_TEXTURE0);
Texture::useTexture(current_mesh->diffuse_map);
glActiveTexture(GL_TEXTURE1);
Texture::useTexture(current_mesh->normal_map);

Third, we remember to unload the program and the attribute:


                glDisableVertexAttribArray (tangentLoc);

                shader->stopProgram(BUMP);


Forth, we use everything in the shader:

vertex:



         varying vec3 eyeVec;
        varying vec3 halfVec;
        varying vec3 lightVec;

        attribute vec3 tangent;

        void main()
        {



               gl_Position = ftransform();

                vec3 n = normalize (gl_NormalMatrix * gl_Normal);
                vec3 t = normalize (gl_NormalMatrix * tangent);
                vec3 b = cross (n, t);

                // output texture coordinates for decal and normal maps
                //gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
                gl_TexCoord[0] = gl_MultiTexCoord0;

                // transform light and half angle vectors by tangent basis
                vec3 v;
                v.x = dot (vec3 (gl_LightSource[1].position), t);
                v.y = dot (vec3 (gl_LightSource[1].position), b);
                v.z = dot (vec3 (gl_LightSource[1].position), n);
                lightVec = normalize (v);

                v.x = dot (vec3 (gl_LightSource[1].halfVector), t);
                v.y = dot (vec3 (gl_LightSource[1].halfVector), b);
                v.z = dot (vec3 (gl_LightSource[1].halfVector), n);
                halfVec = normalize (v);

                eyeVec = vec3 (gl_ModelViewMatrix * gl_Vertex);
                v.x = dot (eyeVec, t);
                v.y = dot (eyeVec, b);
                v.z = dot (eyeVec, n);
                eyeVec = normalize (v);
}

fragment:


varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;

void main (void)
{        vec3 normal = 2.0 * texture2D (normal_map, gl_TexCoord[0].st).rgb - 1.0;
        normal = normalize (normal);


        float lamberFactor= max(dot(lightVec,normal),0.0);
        vec4 diffuseMaterial= vec4(0.0);
        vec4 diffuseLight= vec4(0.0);

        vec4 specularMaterial;
        vec4 specularLight ;
        float shininess ;

        // compute ambient
        vec4 ambientLight = gl_LightSource[1].ambient;

        if (lamberFactor > 0.0)
        {
                diffuseMaterial = texture2D (diffuse_map, gl_TexCoord[0].st);
                diffuseLight  = gl_LightSource[1].diffuse;

                // In doom3, specular value comes from a texture 
                specularMaterial =  vec4(1.0)  ;
                specularLight = gl_LightSource[1].specular;
                shininess = pow (max (dot (halfVec, normal), 0.0), 2.0)  ;

                gl_FragColor =  diffuseMaterial * diffuseLight * lamberFactor ;
                gl_FragColor += specularMaterial * specularLight * shininess ;

        }

        gl_FragColor += ambientLight;

}

And after all this I end up with a uglier version of bumpMapping:

I am a C/C++ guy and I am having difficulties with debugging things in GLSL. I know there are frameworks for that, but the problem is when I connect GLSL and C++. There is no printf() ways in GLSL that I know of. I was trying to use the gl_FragColor to print the information on the screen to double check if everything was passed ok, but I end up with another problem, if I did not use all my variables the programs starts to crash o_O.

I would really appreciate any tips on debugging a shader together with a C++ program or/and any idea of what could be going wrong with this bump mapping.

Just some quick tips.

in the fragment shader you posted, if lamberFactor < 0 you are just setting gl_FragColor to += ambientLight. I’m not sure if there is a default value for gl_FragColor, but this same operation caused me problems on an ATI card, try setting it to ambientLight before you do anything else.

I also use glFragColor to sometimes check if the variables are being set up properly, if you program is crashing because you are not using all the variables that seems to point to a different problem, you should be able to have unused variables in your shaders (Or at least i am able to in my programs). what if you just set gl_FragColor = vec4(1.0,0,0,0); at the start and comment out everything else?

I’ve just started working with GLSL too, and one thing I’ve found to be useful for debugging cases is to set the output color to a solid red/green/blue depending on a conditional value inside the fragment shader. This is the closest you’ll get to a printf, because that is the output of the shader. So one thing you could do that’s real simple is to set the output color equal to the bump mapped normal and you should be able to literally see what’s going on with the texture.

Good luck!

I changed my fragment shader to:


varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;

void main (void)
{        vec3 normal = 2.0 * texture2D (normal_map, gl_TexCoord[0].st).rgb - 1.0;
        normal = normalize (normal);


        float lamberFactor= max(dot(lightVec,normal),0.0);
        vec4 diffuseMaterial= vec4(0.0);
        vec4 diffuseLight= vec4(0.0);

        vec4 specularMaterial;
        vec4 specularLight ;
        float shininess ;

        // compute ambient
        vec4 ambientLight = gl_LightSource[1].ambient;


        gl_FragColor = ambientLight;

        if (lamberFactor > 0.0)
        {
                diffuseMaterial = texture2D (diffuse_map, gl_TexCoord[0].st);
                diffuseLight  = gl_LightSource[1].diffuse;

                // In doom3, specular value comes from a texture 
                specularMaterial =  vec4(1.0)  ;
                specularLight = gl_LightSource[1].specular;
                shininess = pow (max (dot (halfVec, normal), 0.0), 2.0)  ;

                gl_FragColor +=  diffuseMaterial * diffuseLight * lamberFactor ;
                gl_FragColor += specularMaterial * specularLight * shininess ;

        }


}

But nothing changed. :frowning:

The images passed are correct since I set them to the gl_FragColor and it showed the correct results. Do not know what could be wrong. It seems that with the glslDevil I can get more debug information from my program, I am checking it now.

Thank guys, I am open to ideas.

It looks to me that your fragment shader may always be outputting the value of gl_LightSource[1].ambient. Your calculation of lamberFactor looks correct, but when you += gl_FragColor if either of diffuseMaterial or diffuseLight equals 0 you get 0 then (regardless of your lamberFactor calculation). Similarly if specularLight = 0 then you get 0 too. Try eliminating those and check if the result on the screen looks any different from uniform gray.

I would just try to output
gl_FragColor = vec4(vec3(lamberFactor), 1.0);
and see if I get a nonuniform gray output. If I do then the gl_LightSource[1] (or diffuse_map) setup is likely to be screwed up.

May be you need to use gl_LightSource[0] instead of gl_LightSource[1]?

So I found the problem. (Using the gl_FragColor and some tricks to mislead the shader to not discard any variable :slight_smile: )

When I try to render the tangent to the fragment I get:

And rendering the normal I get:

So the tangents are not being passed, right? But I am pretty sure they are computed right as shown in the first post when I draw the normal and the tangent. I will triple check this and how I am passing them.

obs: I am using float instead of GL_FLOAT for the tangents, but I think this is not a big problem is it?

I tried out and it returned a total black creature. Further analyzing the result I also plotted the lightVec and got the same result! So all of these are coming from the vertex shader that is in fact not getting the tangents for some reason… :stuck_out_tongue:

About the gl_LightSource[1], I know it sounds strange, but that is the only light on my system.

Thanks guys for all the help!

I solved the issue some time ago. I am posting the result so that it can help somebody in the same situation.

The problem was the version of GLEW and the calls made. I was using version 1.5.1 of GLEW and I was using the calls without the ARB, when passing the tangents. The result is that no tangents were passed.

It is strange that no error was returned what so ever. Anyway, here are some photos of the result: