Jump to content
  • Advertisement
Sign in to follow this  

OpenGL Weird light behaviour in bump mapping shader

This topic is 3077 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.


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 space
varying vec3 tbnHalfVector; // Half vector in tangent space

uniform 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);


uniform sampler2D texUnit0; //Diffuse
uniform sampler2D texUnit1; //Normal
uniform sampler2D texUnit2; //Opacity, not used here
uniform sampler2D texUnit3; //Specular

struct 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.

Share this post

Link to post
Share on other sites
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);

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!