Here’s my solution:
ARB FP Source coded by JC
OPTION ARB_precision_hint_fastest;
# texture 0 is the cube map
# texture 1 is the per-surface bump map
# texture 2 is the light falloff texture
# texture 3 is the light projection texture
# texture 4 is the per-surface diffuse map
# texture 5 is the per-surface specular map
# texture 6 is the specular lookup table
# env[0] is the diffuse modifier
# env[1] is the specular modifier
TEMP light, color, R1, R2, localNormal, specular;
PARAM subOne = { -1, -1, -1, -1 };
PARAM scaleTwo = { 2, 2, 2, 2 };
# load the specular half angle first, because
# the ATI shader gives a "too many indirections" error
# if this is done right before the texture indirection
#-----------------
#TEX specular, fragment.texcoord[6], texture[0], CUBE;
#MAD specular, specular, scaleTwo, subOne;
# instead of using the normalization cube map, normalize with math
DP3 specular, fragment.texcoord[6],fragment.texcoord[6];
RSQ specular, specular.x;
MUL specular, specular.x, fragment.texcoord[6];
#-----------------
#
# the amount of light contacting the fragment is the
# product of the two light projections and the surface
# bump mapping
#
# perform the diffuse bump mapping
#-----------------
TEX light, fragment.texcoord[0], texture[0], CUBE;
MAD light, light, scaleTwo, subOne;
# instead of using the normalization cube map, normalize with math
#DP3 light, fragment.texcoord[0],fragment.texcoord[0];
#RSQ light, light.x;
#MUL light, light.x, fragment.texcoord[0];
#-----------------
TEX localNormal, fragment.texcoord[1], texture[1], 2D;
MOV localNormal.x, localNormal.a;
MAD localNormal, localNormal, scaleTwo, subOne;
DP3 light, light, localNormal;
# modulate by the light projection
TXP R1, fragment.texcoord[3], texture[3], 2D;
MUL light, light, R1;
# modulate by the light falloff
TXP R1, fragment.texcoord[2], texture[2], 2D;
MUL light, light, R1;
#
# the light will be modulated by the diffuse and
# specular surface characteristics
#
# modulate by the diffuse map and constant diffuse factor
TEX R1, fragment.texcoord[4], texture[4], 2D;
MUL color, R1, program.env[0];
# perform the specular bump mapping
DP3 specular, specular, localNormal;
# perform a dependent table read for the specular falloff
TEX R1, specular, texture[6], 2D;
# modulate by the constant specular factor
MUL R1, R1, program.env[1];
# modulate by the specular map * 2
TEX R2, fragment.texcoord[5], texture[5], 2D;
ADD R2, R2, R2;
MAD color, R1, R2, color;
MUL color, light, color;
# modify by the vertex color
MUL result.color, color, fragment.color;
# this should be better on future hardware, but current drivers make it slower
#MUL result.color.xyz, color, fragment.color;
My GLSL source
varying vec3 Specular_Light_Vector; //fragment.texcoord[6]
varying vec3 Diffuse_Light_Vector; //fragment.texcoord[0]
varying vec2 Normal_Texture_Coordinate; //fragment.texcoord[1]
varying vec2 Light_Projection_Vector; //fragment.texcoord[3]
varying vec2 Light_Falloff_Vector; //fragment.texcoord[2]
varying vec2 Diffuse_Texture_Coordinate; //fragment.texcoord[4]
varying vec2 Sepcular_Texture_Coordinate; //fragment.texcoord[5]
uniform samplerCube Normalization_Cube_Map;
uniform sampler2D Bump_Map;
uniform sampler2D Diffuse_Map;
uniform sampler2D Specular_Map;
uniform sampler2D Light_Falloff_Map;
uniform sampler2D Light_Projection_Map;
uniform sampler2D Specular_Lockup;
uniform vec4 Diffuse_Modifier; //env[0]
uniform vec4 Specular_Modifier; //env[1]
void main()
{
vec3 specular_vec = normalize(Specular_Light_Vector);
vec3 diffuse_vec = textureCube(Normalization_Cube_Map, Diffuse_Light_Vector) * 2.0 - 1.0;
vec3 local_normal = texture2D(Bump_Map, Normal_Texture_Coordinate) * 2.0 - 1.0;
local_normal.x = local_normal.a;
vec4 diffuse = dot(diffuse_vec, local_normal) * texture2DProj(Light_Projection_Map, Light_Projection_Vector) * texture2DProj(Light_Falloff_Map, Light_Falloff_Vector);
vec4 diffuse_color = texture2D(Diffuse_Map, Diffuse_Texture_Coordinate) * Diffue_Modifier;
vec4 specular_color = texture2D(Specular_Map, Specular_Texture_Coordinate) * 2;
vec4 specular = texture2D(vec2(dot(specular_vec, local_normal)), Sepcular_Texture_Coordinate) * Specular_Modifier;
gl_FragColor = (specular * specular_color + diffuse_color) * diffuse * gl_Color;
}