GLSL normal mapping

Started by
2 comments, last by lubiluk 14 years, 11 months ago
Hello everybody. I'm trying to get to work a normal maping glsl shader. It seems to be complete, but the result looks weird. When light is placed somwhere low and relatively far from object for example (0.0,0.0,100.0) it looks fine. ( On my scene 1.0 stands for 1cm) Otherwise when for eg. i point light above object or just somwhere high to have a "normal sun light" it looks strange. there are black stains on object and it seems not natural at all. I can't even say where is the light coming from looking on the object. I suppose there is something wrong with some vector. Maybe someone could tell where is mistake. Here's the procedure: First i set camera:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (float)_screenWidth/(float)_screenHeight, 1.0f, 5000.0f);
// eye is camera position and dir is direction it looks
gluLookAt(eye.x, eye.y, eye.z, eye.x+dir.x, eye.y+dir.y, eye.z+dir.z, 0.0f, 1.0f, 0.0f)
Then setup scene and light:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_LIGHTING);
_lightPosition[0] = 0.0f;
_lightPosition[1] = 0.0f;
_lightPosition[2] = 100.0f;
_lightPosition[3] = 0.0f;
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, _lightPosition);
Then objects on scene are rendered with use of:

glPushMatrix();
// mat is object's position matrix
glMultMatrixf(mat);
//below function render() will be listed
object.render();
glPopMatrix();
Here is simplified render funcion. All wertices of object are given in local space.

glUseProgram(shader);
glUniform1i(shader, "diffuseMap", 0);
glUniform1i(shader, "normalMap", 1);
/* ... binding textures here ... */

/* And draw mesh procedure*/

/* for all faces->vertices... as usual */
glBegin(GL_TRIANGLES);
glNormal3f(normal.x, normal.y, normal.z);
// Below i send tangent via color to shader
// because i didn't manage yet to do it with attribute
glColor3f(tangent.x, tangent.y, tangent.z);
glMultiTexCoord2f(GL_TEXTURE0, txcord.u, txcord.v);
glMultiTexCoord2f(GL_TEXTURE1, txcord.u, txcord.v);
glVertex3f(vertex.x,vertex.y,vertex.z);
glEnd();
glUseProgram(0);
Ok here is shader code. Vertex shader:

varying vec3 L;

void main() 
{
	// normal map computing
	gl_TexCoord[0] = gl_MultiTexCoord0;
	gl_TexCoord[1] = gl_MultiTexCoord1;
	
	L = vec3(gl_LightSource[0].position - gl_ModelViewMatrix * gl_Vertex);
	L = normalize(L);	
	
	vec3 N = normalize(gl_NormalMatrix * gl_Normal);
	vec3 T = gl_Color.xyz;
	
	vec3 B = cross(T,N); 	
	
	mat3 TBN = mat3(T,B,N);
	
	L = TBN * L;
					
	// vertex transform
	gl_Position = ftransform();
}
Framgent shader:

varying vec3 L;
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

void main() 
{
	vec3 rgb = texture2D(diffuseMap, gl_TexCoord[0]).rgb;
	vec3 normal = texture2D(normalMap, gl_TexCoord[1]).xyz;
	normal = (normal - 0.5) * 2;
	L = normalize(L);
	vec3 NdotL = dot(normal,L);
	
	gl_FragColor.rgb = rgb * NdotL;
}
I've spent a couple of days trying figure out what is wrong bot can't find anything. I would really apreciate if someone look at this code. I think it may be something with global and local vectors. I'm not quite sure if it's right way to get light vector. Here's screen when light is positioned at (0.0,1000.0,500.0) and character is at (0,0,0). http://img15.imageshack.us/img15/9638/normale.png
Advertisement
Haven't looked deeply in it, but the first thing that I see that is wrong is using the color interpolator for passing the tangent vector. Colors are in [0;1] while your tangent values will be in [-1;1]. Even if you normalized them in [0;1] range, the precision is relatively low (8 bits) so you should use a tex coord interpolator for that instead.

Y.
Thanks, that solved problem with stains, now it gives right bump effect, I can see where the light is coming from by looking on model... and that's another problem. I positioned light at pos:
_lightPosition[0] = 0.0f;_lightPosition[1] = 10000.0f;_lightPosition[2] = 0.0f;_lightPosition[3] = 0.0f;

But it seems light is always on floor.
Something with processing light vector?

Btw. How can i handle directional light which isn't attached to one point on the scene but everywhere is same?
I don't get it. When light is set on z axis it works fine. But any values at x and y does't give avy result. I don't have a clue why
varying vec3 L;varying vec4 specular;void main() {	// vertex transform	gl_Position = ftransform();	gl_TexCoord[0] = gl_MultiTexCoord0;	gl_TexCoord[1] = gl_MultiTexCoord1;	gl_TexCoord[2] = gl_MultiTexCoord2;	L = vec3(0.0,1.0,0.0);		vec3 normal = normalize(gl_Normal);	vec3 tangent = vec3(gl_MultiTexCoord5.xyz);	vec3 binormal = cross(tangent,normal); 			mat3 TBN = gl_NormalMatrix * mat3(tangent, binormal, normal);		L = TBN * L;}

The result is always same as light position is 0.0 0.0 1.0 when z has some value differend than 0.0. Otherwise when z = 0.0 model is all black. Does anyone had same problem?

This topic is closed to new replies.

Advertisement