Sign in to follow this  

GLSL Specular Map question

This topic is 4788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I finally got normal maps working (and they look fantastic!). My next quest is to get specular maps working. Doom3 specular maps are either RGBA or RGB textures, so my initial guess is to do something like this:
    // final color
    gl_FragColor = gl_FrontMaterial.emission;
    gl_FragColor += gl_LightModel.ambient * gl_FrontMaterial.ambient;
    gl_FragColor += attenuation * spotlight * (gl_FrontLightProduct[0].ambient + (diffuse * gl_FrontLightProduct[0].diffuse) + (specular * gl_FrontMaterial.shi
niness * speccolor));
    gl_FragColor *= texcolor;

Where speccolor is gotten from this:
    // get the specular color
    vec4 speccolor = texture2D(specmap, vec2(gl_TexCoord[0])) * gl_LightSource[0].specular;

I'm putting the half vector into tangent space:
    H = normalize(tbn * gl_LightSource[0].halfVector.xyz);

But, I think I've got a problem in that I don't know if the half-vector starts in object or eye space (I think eye space, which would mean I'm not actually putting it into tangent space). I'm also not sure if I'm applying the specular map correctly (I can't find any GLSL tutorials or non-grayscale tutorials at the moment). I'm also not sure of what to set the shininess factor to since it's not encoded in the specular map. I guess I'm basically asking for any advice or links I can get. I don't see this being as hard to figure out as normal maps, I just don't know if I'm on exactly the right track yet.

Share this post


Link to post
Share on other sites
Okay, I actually think I got this one on my own. I'd still appreciate someone looking it over though, if that's okay:

vertex shader:

attribute vec4 tangent;

varying vec3 L, SD, H;
varying float distance;

void main(void)
{
// set the vertex position in eye space
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

// create the tangent matrix
mat3 tbn;
tbn[0] = tangent.xyz;
tbn[1] = cross(tangent.xyz, gl_Normal) * tangent.w;
tbn[2] = gl_Normal;

// get the light position in object space
vec4 P = gl_ModelViewMatrixInverse * gl_LightSource[0].position;

if(gl_LightSource[0].position.w != 0.0) {
// then the vector from the light to the vertex
vec4 LV = P - gl_Vertex;
distance = length(LV.xyz);

// put the light vector into tangent space
L = normalize(tbn * LV.xyz);
} else {
distance = 1.0;

// put the light vector into tangent space
L = normalize(tbn * P.xyz);
}

vec4 half = gl_ModelViewMatrixInverse * gl_LightSource[0].halfVector;

SD = normalize(tbn * gl_LightSource[0].spotDirection);
H = normalize(tbn * half.xyz);

// setup the vertex textures
gl_TexCoord[0] = gl_MultiTexCoord0;
}



fragment shader:

uniform sampler2D detail, normalmap, specmap;

varying vec3 L, SD, H;
varying float distance;

void main(void)
{
// get the attenuation
float attenuation = 1.0;
if(gl_LightSource[0].position.w != 0.0) {
float distance2 = distance * distance;

attenuation = 1.0 / (gl_LightSource[0].constantAttenuation +
(gl_LightSource[0].linearAttenuation * distance) +
(gl_LightSource[0].quadraticAttenuation * distance2));
}

// get the spotlight
float spotlight = 1.0;
if(gl_LightSource[0].spotCutoff != 180.0) {
float value = max(dot(L, SD), 0.0);
if(value < gl_LightSource[0].spotCosCutoff)
spotlight = 0.0;
else
spotlight = pow(value, gl_LightSource[0].spotExponent);
}

// get the normal
vec3 normal = normalize(2.0 * texture2D(normalmap, vec2(gl_TexCoord[0])).xyz - 1.0);

// get the diffuse amount
float diffuse = max(dot(L, normal), 0.0);

// get the specular amount
float specular = max(dot(H, normal), 0.0);

// get the specular color
vec4 speccolor = texture2D(specmap, vec2(gl_TexCoord[0])) * gl_LightSource[0].specular;

// get the texture color
vec4 texcolor = texture2D(detail, vec2(gl_TexCoord[0]));

// final color
float temp = attenuation * spotlight;
gl_FragColor = gl_FrontLightModelProduct.sceneColor;
gl_FragColor += temp * (gl_FrontLightProduct[0].ambient + (diffuse * gl_FrontLightProduct[0].diffuse));
gl_FragColor *= texcolor;

// seperate specular
gl_FragColor += temp * (pow(specular, gl_FrontMaterial.shininess) * speccolor);
}



It seems to work. I see a sort of gloss on the metalic sections of the models. I assume that's what I should be seeing? The gloss moves as I move, just as I would expect in the real world. It's really subtle though and I cranked the shininess up to 128. It's a cool effect, I just hope I'm doing it properly.

Share this post


Link to post
Share on other sites

This topic is 4788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this