GLSL normal map

I’m new here so… Hi :smiley:

I’m very new to GLSL (and shaders in general), been trying it out now for all of the last two days so I am looking for some good feedback please.
Been writing a few simple shaders, mostly using tutorials like lighthouse3D etc. The usual toon, point lights etc. Bit of reference from a HLSL dvd(light theory etc).

I decided to try out a normal map equipped shader - I think it is ok, but I have come to the point where I have looked through so many different tutorials, forum posts etc that I’m just not sure any more if it is ok or not…

If anyone has time to have a scan for noobish errors or to give hints that would be great.

I decided to dump it in with a single point light phong model.

Vert shader:


varying vec3 normal;
varying vec3 lightDir;
varying vec3 lightDirTS;
varying vec3 eyeVecTS;
varying float atten;

varying vec4 ambientGlobal;
varying vec4 ambient;
varying vec4 diffuse;

attribute vec3 tangent;
attribute vec3 binormal;

void main(void)
{
	// Transform normal to eye-space
	normal = normalize( gl_NormalMatrix * gl_Normal );
	// Transform vertex to eye-space
	vec4 vertPos = gl_ModelViewMatrix * gl_Vertex;

	// Create transformation matrix
	mat3 mTBN = mat3( tangent, binormal, gl_Normal );

	// Calc vector from light to vertex & then normalise
	vec3 dir = vec3( gl_LightSource[0].position - vertPos );
	lightDir = normalize( dir );

	// Calc light dir in tangent space
	vec3 dirTemp = mTBN * normalize( dir );
	lightDirTS = normalize( dirTemp );

	// Calc eye vector in tangent space
	vec3 eyeTemp = mTBN * normalize( vec3(-vertPos) );
	eyeVecTS = normalize( eyeTemp );

	// Calc distance between vertex & light
	float dist = length( dir );
	// Calc attenuation
	atten = 1.0 / ( gl_LightSource[0].constantAttenuation +
					gl_LightSource[0].linearAttenuation * dist +
					gl_LightSource[0].quadraticAttenuation * dist * dist );
	atten = clamp( atten, 0.0, 1.0 );

	// Ambient components
	ambientGlobal = gl_FrontMaterial.ambient * gl_LightModel.ambient;
	ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;

	// Diffuse component
	diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;

	// Use first set of texcoords in fragment shader
	gl_TexCoord[0] = gl_MultiTexCoord0;

	// Position handled using fixed functionality
	gl_Position = ftransform();
}

Frag shader:


varying vec3 normal;
varying vec3 lightDir;
varying vec3 lightDirTS;
varying vec3 eyeVecTS;
varying float atten;

varying vec4 ambientGlobal;
varying vec4 ambient;
varying vec4 diffuse;

uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

void main(void)
{
	vec3 N = normalize( normal );
	vec3 L = normalize( lightDir );
	vec3 Ln = normalize( lightDirTS );

	// Sample diffuse map
	vec4 diffMap = texture2D( diffuseMap, gl_TexCoord[0].st );
	// Sample normal map in -1.0 to 1.0 space
	vec3 Nn = normalize( texture2D(normalMap, gl_TexCoord[0].st).xyz * 2.0 - 1.0 );
	Nn.y = -Nn.y;

	// Calc diff/ambient contribution from normal map
	float LnDotNn = max( dot(Ln, Nn), 0.0 );

	// Final colour always includes any contribution from global ambient
	vec4 colour = ambientGlobal * LnDotNn * diffMap;

	// If norm dot light dir is > 0 then calc diffuse & specular contributions
	float NDotL = max( dot(N, L), 0.0 );
	if ( NDotL > 0.0 )
	{
		// Normalise the interpolated eye vector & Calc reflection vector of light from normal
		vec3 eye = normalize( eyeVecTS );
		vec3 ref = reflect( -Ln, Nn );

		// Calc dot product of eye & reflection vectors, clamp between 0 & 1
		float refDotEye = max( dot(ref, eye), 0.0 );

		// Calc specular component taking into account attenuation
		vec4 spec = gl_FrontMaterial.specular * gl_LightSource[0].specular *
					pow( refDotEye, gl_FrontMaterial.shininess );

		// Self-Shadowing
		float shadow = saturate( 4.0 * NDotL );

		// Add light components taking into account attenuation
		colour += atten * clamp( shadow * (diffMap * LnDotNn * (ambient + diffuse) + spec), 0.0, 1.0 );
	}

	gl_FragColor = colour;
}