I have been trying to get a gloss map working, with a multi pass algorithm and “vanilla” ARB_texture_env_combine, for the last couple of days. Basically I have been trying the following:
- Render the model with Diffuse only
- Render the DOT3 bumps
This is working fine but I get the “Plastic” look that has been a topic of a previous post. I am now trying to add a gloss map to step 2.
I have been trying to do this using the following setup for Texture Unit 3:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
I have the Normal map bound to TU1, the Normalisation cubemap bound to TU2 and the Gloss map bound to TU3. The Gloss map is an 8 bit grey scale image loaded as GL_LUMINANCE (I have tried GL_ALPHA and GL_INTENSITY with various setups for TexEnv and blending).
When I combine the two passes I have tried different setups for blending but have found the best results seem to be when I use:
glBlendFunc ( GL_DST_ALPHA, GL_ONE );
The problem I have is that I end up with portions of the model being darker than they should be because of the addition of the gloss map. I can’t for the life of me figure out why. In my mind if I am using the above blending function then it should be doing “SRC_C * DST_A + DST_C” - so if a fragment in the src is black, the result should just be the destination colour.
Here are some pictures that show the problems:
- Diffuse Only model
- Bump mapped
- Bump and Gloss map Output
- Diffuse, Bump and Gloss map Output
Is there anything obvious that I’m missing or does anyone have any tute’s that might help? Is what I am attempting even possible?
Your screenshots didn’t work for me, but I can tell you that multiplying your source color by destination alpha in the blendfunc is not what you want unless you have your glossmap stored in destination alpha. I did that here for example, http://www.sgi.com/products/software/performer/brew/aqua.html#_cch3_886491694 but I did it because hardware only had a single texture unit and limited capabilities:
Just go with a glBlendFunc(GL_ONE, GL_ONE).
Alternatively you could send the gloss map straight out the alpha channel in the specular pass and then simply do a glBlendFunc(GL_SRC_ALPHA, GL_ONE) leaving the combiners otherwise setup exactly the same as they were without the glossmap. Just let the blendfunc do the glossmap modulation using gloss alpha, the drawback is your glossmap must then be monochrome but it probably is anyway so it is not a drawback at all. This requires that the specular term is shaded as an independent pass but it seems that’s what you’re doing anyway.
Looks like the DNS servers I use are up the proverbial…
The gloss map I upload is an 8 bit LUMINANCE texture (single channel grey scale). I have tried uploading it as GL_ALPHA, GL_LUMINANCE and GL_INTENSITY. GL_LUMINANCE gives results, the rest mostly give just a black screen. I don’t use Additive blending because it gives me artifacts where the destination has alpha less than 1 (the edge of the wings in the example model has a frayed edge that is done with alpha). For the most part the destination alpha is 1 so it’s roughly equivalent to using GL_ONE, GL_ONE.
The major issue as I see it is that even if I am using additive blending, portions of my model are being darkened by the Bump/Gloss map pass. To me this looks like the output from the DOT3 bump setup, when multiplied by the gloss map, it creating -ve values. Which I didn’t think was possible. Or is it possible and the clamping isn’t done until after blending?
The only way I can see past this problem is to do 3 passes (and I don’t know if this works I’ll try it later). The first pass is the gloss map, which puts alpha into the buffer. The second is the bump map, which gets multiplied by the Destination Alpha. And the last is the diffuse - which get’s added to the first two passes. Does that sound feasible?
OK I finally figured it out. I now do 3 passes to get the desired results:
- Gloss map
- Bump map
The gloss map is loaded as GL_LUMINANCE and is written to the buffer using GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA.
The Bump mapping is done as normal and is blended with the Destination with GL_DST_COLOR, GL_ZERO.
Then finally the Diffuse is done using additive blending (GL_ONE, GL_ONE).
To me it should be possible with a single pass for Gloss/Bump and a second for diffuse - but I couldn’t get it to work…
Now onto the vp/fp code path (yek…)
I’d suggest that you study a bit more how per-pixel lighting works - especially the part about specular and gloss maps. These should be added after you do the multiplication of the diffuse and the normal map. Ie. you’re doing “gloss * normal + diffuse”, while you should be doing “normal1 * diffuse + normal2 * gloss”, where “normal1” is N dot L (normal dot light vector), and “normal2” is a power of N dot V (normal dot half angle vector).
But N.L * Diffuse gives me the result shown in Image 2 of my original post. The last thing I want is that PLUS extra lighting. What I want to do is reduce the effect of the N.L in the areas that I do not want to appear either plastic or metalic.
N.L is the diffuse lighting term – it’s view-independent and does not lead to a plastic or metallic look. You do not want this term to be affected by the gloss map, you just want to multiply it with the base texture.
The much-bemoaned plastic look comes from specular highlights, and from your description so far I’m not even sure if you have those at all? In any case, the specular term is the one you want to multiply with the gloss map. This result can them be added (not multiplied!) to the previous term (N.L * texture).
Check out my article for more details on all this.
If you look at your diffuse model (image1), it already has some specular highlights embedded in it. I’d blame your “plastic look” more on the textures used than your lighting equation.
Originally posted by Tom Nuydens:
N.L is the diffuse lighting term
Yes you are right, now I’m getting confused.
If you look at image 1 in the original post, this is N.L * Diffuse - ie. without specular. Yes there are “specular highlights” in the texture, but I am not concerned about them, they can easily be removed.
If you look at Image 2, that is Image + a specular pass that is generated via DOT3 bump mapping. If you look at the models left thigh, up near the top, you can see a large specular highlight and the plastic look comes from the entire model having the same specular exponent. ie. There is no variation in the specular output so it looks to be made of the same material.
I want to be able to alter that using a gloss map, which I can now do. I multiply the output of the Specular pass by the gloss map. I was trying to do this in a single pass, but couldn’t get it to work (that was the subject of my question). I can now get it done in two passes as I have described.
The solution I came up with requires that I start with the gloss map, then do the specular and then add the diffuse. So far I’ve been told “No you do it the other way round” so there must be a way you can do Gloss & Specular at the same time. Remembering that I just want to use ARB_texture_env_combine.
Thanks for the link Tom I will have a look at the article tomorrow sometime…
Okay, I understand now. Obviously, it doesn’t matter whether you do diffuse + specular or specular + diffuse. If it’s easier for you, for implementation reasons, to do it the other way around, that’s fine.
Should you want to try it in the suggested order, you could render gloss to destination alpha, then render diffuse to RGB, then render specular with blendfunc(DST_ALPHA, ONE). Obviously, if you have a texture unit to spare, even better would be to render specular * gloss in a single pass with blendfunc(ONE, ONE).
The screenshots work for me now. I’d say that screenshot 2 is probably correct or pretty close to it. It’s not clear what you’re expecting but adjusting the overall albedo for diffuse as a function of time or under mouse/keyboard input might help you test the lighting contributions by editing one term independently of another.