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.