I usually don't use pure normal mapping, but offset mapping. But I found this in my source tree...it might be a start:
Normal mapping fragment shader:
precision mediump float;
varying vec3 lightVec[2];
varying vec3 eyeVec;
varying vec2 texCoord;
uniform sampler2D textureUnit0;
uniform sampler2D textureUnit1;
uniform vec3 diffuseColors[8];
uniform vec3 specularColors[8];
uniform vec4 ambientColor;
uniform float invRadius;
uniform float heightScale;
varying float angle;
void main ()
{
vec4 vAmbient = ambientColor;
vec3 vVec = normalize(eyeVec);
float height = texture2D(textureUnit1, texCoord).a;
vec2 offset = vVec.xy * (height * 2.0 - 1.0) *heightScale;
vec2 newTexCoord = texCoord + offset;
vec4 base = texture2D(textureUnit0, newTexCoord);
vec3 bump = normalize(texture2D(textureUnit1, newTexCoord).xyz * 2.0 - 1.0);
// First light source
//float distSqr = dot(lightVec[0], lightVec[0]);
float distSqr = min(65500.0, dot(lightVec[0], lightVec[0]));
float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
vec3 lVec = lightVec[0] * inversesqrt(distSqr);
float diffuse = max(dot(lVec, bump), 0.0);
vec4 vDiffuse = vec4(diffuseColors[0],0) * diffuse;
float specular = pow(clamp(dot(reflect(-lVec, bump), vVec), 0.0, 1.0), 0.85);
vec4 vSpecular = vec4(specularColors[0],0) * specular;
gl_FragColor = (vAmbient*base + vDiffuse*base + vSpecular) * att*2.0*angle;
}
...and the corresponding vextex shader:
uniform mat4 modelViewMatrix;
uniform mat4 modelViewProjectionMatrix;
uniform vec4 additionalColor;
uniform vec4 ambientColor;
uniform vec3 lightPositions[8];
attribute vec4 position;
attribute vec3 normal;
attribute vec4 tangent;
attribute vec2 texture0;
varying vec3 lightVec[2];
varying vec3 eyeVec;
varying vec2 texCoord;
varying float angle;
void main(void)
{
texCoord = texture0.xy;
vec3 n = normalize(modelViewMatrix * vec4(normal,0.0)).xyz;
vec3 t = normalize(modelViewMatrix * vec4(tangent.xyz, 0.0)).xyz;
vec3 b = tangent.w*cross(n, t);
vec3 vVertex = vec3(modelViewMatrix * position);
vec3 tmpVec = lightPositions[0].xyz - vVertex;
angle = max(0.0, dot(n, normalize(tmpVec)));
angle=1.0;
vec3 lv;
vec3 ev;
lv.x = dot(tmpVec, t);
lv.y = dot(tmpVec, b);
lv.z = dot(tmpVec, n);
lightVec[0]=lv;
tmpVec = vVertex*-1.0;
eyeVec.x = dot(tmpVec, t);
eyeVec.y = dot(tmpVec, b);
eyeVec.z = dot(tmpVec, n);
gl_Position = modelViewProjectionMatrix * position;
}
When using these, make sure to assign the shader before calling build() on the Object3D, so that jPCT-AE can do it's magic and inject the tangent vectors to the shader.