Weird light behaviour in bump mapping shader

Started by
0 comments, last by Farfadet 13 years, 9 months ago
I implemented a test bump map shader from some tutorials and it produces great results, except the light, it is being affected by the camera direction. I want it to be fixed in global space. I cant find what seems to be the problem.

Vert:
uniform mat4 World;uniform mat4 View;uniform mat4 Proj;attribute vec3 tangent;attribute vec3 bitangent;struct lightDataType{    vec4  ambient;     vec4  diffuse;     vec4  specular;     vec4  position; // Position in eye coordinates};varying vec3 tbnDirToLight; // Direction to light in tangent spacevarying vec3 tbnHalfVector; // Half vector in tangent spaceuniform vec3 mEye; //Camera eye in global space?void main (void){   mat4 VP = (Proj * View);   mat4 WVP = (Proj * View * World);   mat4 WV = (View * World);   mat4 W = World;   mat4 V = View;   mat4 P = Proj;gl_Position = WVP * vec4(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0);gl_TexCoord[0] = gl_MultiTexCoord0;	  lightDataType light;	  light.position = vec4(0, 5, 0, 1); //Not sure what goes here	  vec3 mvNormal = vec3(WV * vec4(gl_Normal, 1.0)); //If its 0 at the end it produces incorrect results	  vec3 mvTangent = vec3(WV * vec4(tangent, 1.0));	  vec3 mvBinormal = vec3(WV * vec4(bitangent, 1.0));	  vec3 mvVertex = vec3(WV * gl_Vertex);	  //vec3 mvDirToEye = mEye - mvVertex;	  vec3 mvDirToEye = -mvVertex;	  vec3 tbnDirToEye;	  tbnDirToEye.x = dot(mvDirToEye, mvTangent);	  tbnDirToEye.y = dot(mvDirToEye, mvBinormal);	  tbnDirToEye.z = dot(mvDirToEye, mvNormal);    	  vec3 mvDirToLight = vec3(light.position) - mvVertex;	  tbnDirToLight.x = dot(mvDirToLight, mvTangent);	  tbnDirToLight.y = dot(mvDirToLight, mvBinormal);	  tbnDirToLight.z = dot(mvDirToLight, mvNormal);        	  tbnHalfVector = normalize(tbnDirToEye + tbnDirToLight);}


Frag:
uniform sampler2D texUnit0; //Diffuseuniform sampler2D texUnit1; //Normaluniform sampler2D texUnit2; //Opacity, not used hereuniform sampler2D texUnit3; //Specularstruct lightDataType{    vec4  ambient;     vec4  diffuse;     vec4  specular;     vec4  position;};varying vec3 tbnDirToLight;varying vec3 tbnHalfVector;void main(void){		lightDataType light;		light.ambient = vec4(0.4, 0.4, 0.4, 1.0);		light.diffuse = vec4(0.4, 0.4, 0.4, 1.0);		light.specular = vec4(0.45, 0.45, 0.45, 1.0);		float shininess = 100.0;		vec4 baseColour = texture2D(texUnit0, gl_TexCoord[0].xy);		vec3 normal = normalize(texture2D(texUnit1, gl_TexCoord[0].xy).xyz * 2.0 - 1.0);		//normal.y = -normal.y; //UNCOMMENT IF WRONG   		vec4 ambient = light.ambient * baseColour;    		vec3 tbnNormDirToLight = normalize(tbnDirToLight);		float diffuseIntensity = max(dot(tbnNormDirToLight, normal), 0.0);		vec4 diffuse = light.diffuse * baseColour * diffuseIntensity;		vec4 specular = vec4(0.0, 0.0, 0.0, 0.0);		if(diffuseIntensity > 0.0)		{			vec4 specularColour = texture2D(texUnit3, gl_TexCoord[0].xy); 			float specularModifier = max(dot(normal, normalize(tbnHalfVector)), 0.0); 			specular = light.specular * specularColour * pow(specularModifier, shininess);		}		gl_FragColor = clamp(ambient + diffuse + specular, 0.0, 1.0);		gl_FragColor.a = baseColour.a;}


Im pretty sure its some mistake to do with opengl spaces, pls help.
Advertisement
A vertex shader transforms vertices from world space into clipping coordinates space (screen space) (with the modelview-projection matrix), but also needs to transform the vectors, if they are fixed in world space. This is not evident, but you need another matrix to transform vectors : the normal matrix (gl_NormalMatrix). This is explained in the orange book, ch. 6.2.

When I want my light source to be fixed in global space (i.e. turning with the scene) I add the line :

LightPosition = vec3(gl_NormalMatrix * LightPosition);

And just remove it when I want the light fixed in screen coordinates (always coming from the same apparent direction)

I also apply this transformation to the normal, tangent and binormal vectors :

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

This topic is closed to new replies.

Advertisement