Hi,
I'm trying to learn more about Normal Mapping and I'm getting
really close to finishing a working GLSL Normal Mapping shader, but I'm having a problem for which I hope someone here has a solution.
Here is the situation:
By reading and combining bits and pieces from different articles (these marvellous tutorials really got me going:
First,
Second) I managed to make a working GLSL shader that seems to work in Shader Designer (TyphoonLabs) but when using the shader in my own render-engine, problems arise. It seems I don't transform the light and/or camera position correctly into Tangent Space, so Specular and Diffuse Lighting are a bit "off" (see screenshot below).
Here is the problem:
The real path of the light follows the green line in the screenshot (it just rotates around the Y-axis at a fixed height above the plane), but the light on the "surface" of the quad follows the red line (more or less)! I hope you understand what I mean :)
The result sure "looks" like Normal Mapping, but just the lighting is wrong.
Surely there is something wrong in my shader, but I'm a bit stumped (as these are my first steps towards Normal Mapping).
At first I thought my TBN-Matrix was wrong (perhaps I used wrong Texture Coordinates?), and to be sure I placed the Quad at the origin with the normal pointing towards the positive Y-axis and hardcoded the Tangent and Binormal vectors in my app ... but the problem still exists.
These are the hardcoded values I'm using:
Vector3 tangent = new Vector3(1.0, 0.0, 0.0);
Vector3 normal = new Vector3(0.0, 1.0, 0.0);
Vector3 binormal = new Vector3(0.0, 0.0, 1.0);
This is my GLSL vertex shader:
varying vec4 viewTangetSpace;
varying vec4 lightTangetSpace;
attribute vec3 tangent; //These are the hardcoded attributes from my app
attribute vec3 binormal; //These are the hardcoded attributes from my app
//Light and Camera position in WorldSpace, which I get from my app
uniform vec4 lightPos, cameraPos;
void main(void)
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
mat3 TangentSpace_Matrix = mat3(tangent, binormal, gl_Normal);
vec3 viewDir = cameraPos.xyz - gl_Vertex.xyz;
viewTangetSpace.xyz = viewDir * TangentSpace_Matrix;
viewTangetSpace.w = 1.0;
viewTangetSpace = normalize(viewTangetSpace);
vec3 lightVec = lightPos.xyz - gl_Vertex.xyz;
lightTangetSpace.xyz = lightVec * TangentSpace_Matrix;
lightTangetSpace.w = 1.0;
lightTangetSpace = normalize(lightTangetSpace);
}
This is my GLSL fragment shader:
varying vec4 viewTangetSpace;
varying vec4 lightTangetSpace;
uniform sampler2D texture;
uniform sampler2D normalMap;
void main()
{
const float shine = 64.0;
vec4 normalVector = texture2D(normalMap, vec2(gl_TexCoord[0]));
normalVector = normalVector * 2.0 - 1.0;
normalVector.a = 0.0;
vec4 color = texture2D(texture, vec2(gl_TexCoord[0]));
vec4 lightReflection = normalize( reflect(-lightTangetSpace, normalVector) );
//specular lighting
vec4 localView = normalize(viewTangetSpace);
float intensity = max(0.0, dot(lightReflection, localView) );
vec4 specular = vec4(pow(intensity, shine));
//diffuse lighting
float NdotL = max(dot(normalVector, normalize(lightTangetSpace)), 0.0);
vec4 diffuse = NdotL * color;
gl_FragColor = 0.2 * color + (diffuse * color + 0.6 * specular);
}
I'm probably overlooking something trivial but I really can't see what I'm doing wrong. Perhaps someone here sees a solution?
Thanks a lot in advance!