GLSL Specular Map question

Started by
0 comments, last by Chozo 19 years, 4 months ago
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.
Advertisement
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.

This topic is closed to new replies.

Advertisement