Two textures, a colormap, a mixmap, and dynamic lighting
All,
Some weeks ago I was aided greatly in this forum in figuring out how to use an RGBA texture as a colormap ( the RGB components ) and mixmap ( the alpha component ) for a terrain system.
http://www.idevgames.com/forum/showthread.php?t=7421
The code works, excellently.
Now, recently I've started to add dynamic lighting from effects in my game, like lasers and particle-system explosions and all that crap. The lighting works nicely for non-terrain geometry. [ for reference, the terrain lights correctly when texturing is turned off ]
So, here's my setup:
Unfortunately, the solution reached for the mixmap blending is a little magical to me. I understand why it works, but I can't really figure out how to change it to allow the lighting of the underlying geometry to shine through.
I've made several modifications that I thought might do it, but none do. I've posted the original, not-mucked-with code.
If anybody has some insight, could you help me?
Some weeks ago I was aided greatly in this forum in figuring out how to use an RGBA texture as a colormap ( the RGB components ) and mixmap ( the alpha component ) for a terrain system.
http://www.idevgames.com/forum/showthread.php?t=7421
The code works, excellently.
Now, recently I've started to add dynamic lighting from effects in my game, like lasers and particle-system explosions and all that crap. The lighting works nicely for non-terrain geometry. [ for reference, the terrain lights correctly when texturing is turned off ]
So, here's my setup:
Code:
if ( _primaryTextureID )
{
glActiveTextureARB( GL_TEXTURE0_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _primaryTextureID );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0.0f);
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glScalef( _primaryTextureScale, _primaryTextureScale, 1.0f );
glTranslatef( -_xyScaleOverTwo, -_xyScaleOverTwo, 0.0f );
glMatrixMode( GL_MODELVIEW );
}
if ( !_secondaryTextureID )
{
/*
Set the colormap texture to TEXTURE2,
and set up a scaling matrix to stretch
it across the whole terrain, using
automatic tex coord generation
*/
glActiveTextureARB( GL_TEXTURE1_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _colormapTextureID );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glScalef( _oneOverXYScale, _oneOverXYScale, 1.0f );
glTranslatef( -_xyScaleOverTwo, -_xyScaleOverTwo, 0.0f );
glMatrixMode( GL_MODELVIEW );
}
else
{
glActiveTextureARB( GL_TEXTURE1_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _secondaryTextureID );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
glTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0.0f);
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glScalef( _secondaryTextureScale, _secondaryTextureScale, 1.0f );
glMatrixMode( GL_MODELVIEW );
/*
Set up mixmap blending, use alpha channel of TEXTURE2
as interpolative factor between TEXTURE0 and TEXTURE1
*/
glActiveTextureARB( GL_TEXTURE2_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _colormapTextureID );
glTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glScalef( _oneOverXYScale, _oneOverXYScale, 1.0f );
glTranslatef( -_xyScaleOverTwo, -_xyScaleOverTwo, 0.0f );
glMatrixMode( GL_MODELVIEW );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE1_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE0_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE2_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA );
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
/*
Set up colormap blending
Bind colormap to TEXTURE3, & set the TEXTURE_ENV_COLOR for
to solid white with solid alpha, so TEXTURE3's alpha component
is ignored
*/
glActiveTextureARB( GL_TEXTURE3_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _colormapTextureID );
glTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glScalef( _oneOverXYScale, _oneOverXYScale, 1.0f );
glTranslatef( -_xyScaleOverTwo, -_xyScaleOverTwo, 0.0f );
glMatrixMode( GL_MODELVIEW );
/*
I THINK THE TROUBLE LIES HERE
*/
GLvector4f white = { 1, 1, 1, 1 };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, white);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}Unfortunately, the solution reached for the mixmap blending is a little magical to me. I understand why it works, but I can't really figure out how to change it to allow the lighting of the underlying geometry to shine through.
I've made several modifications that I thought might do it, but none do. I've posted the original, not-mucked-with code.
If anybody has some insight, could you help me?
So, this is what I get out of your code (the "else" path):
So there's a few things that probably aren't right here... first, the work done by unit0 is ignored, you never use it.
Second, your setup on unit3 is ignored, because you never specify COMBINE mode. Remember, the texture mode defaults to MODULATE, and the source, operand, etc setup doesn't affect any mode except for COMBINE.
Third, you're using four units when you could get the current result with only two (although, you have three textures, so you still need at least three units.)
OK, now for your original question... you want to modulate all of the texturing result with the lit primary color, right? So you need a pass at the end to do that. You could use a texture unit with MODULATE (PREVIOUS, PRIMARY_COLOR) to get the diffuse light component. You need another pass if you want specular.
Code:
unit0: MODULATE: TEX0 * PRIMARY COLOR
unit1: REPLACE: TEX1
unit2: COMBINE: TEX1 * TEX2_a + TEX1 * (1-TEX2_a)
unit3: MODULATE: TEX3 * unit2Second, your setup on unit3 is ignored, because you never specify COMBINE mode. Remember, the texture mode defaults to MODULATE, and the source, operand, etc setup doesn't affect any mode except for COMBINE.
Third, you're using four units when you could get the current result with only two (although, you have three textures, so you still need at least three units.)
OK, now for your original question... you want to modulate all of the texturing result with the lit primary color, right? So you need a pass at the end to do that. You could use a texture unit with MODULATE (PREVIOUS, PRIMARY_COLOR) to get the diffuse light component. You need another pass if you want specular.
How's this look?
Code:
unit0: COMBINE: TEX0 * TEX2_a + TEX1 * (1-TEX2_a)
unit1: COMBINE: unit0 * TEX2_rgb
unit2: MODULATE: unit1 * PRIMARY_COLOR
That looks logical; the trouble is I'm over my head here... is there any chance you could skeleton it? I'm really not grokking COMBINE particularly well.
As always, I really appreciate your help, arrekusu.
EDIT: I wrote this in my COMBINE testbed app -- how's it look?
In my testbed app, it seems to work...
I get texture mixing, colormap application, and color interpolation between vertices. Seems right to me... I guess I'll put it in my game and cross my fingers.
As always, I really appreciate your help, arrekusu.
EDIT: I wrote this in my COMBINE testbed app -- how's it look?
Code:
/*
Bind textures
TEXTURE0 : Primary Texture
TEXTURE1 : Secondary Texture
TEXTURE2 : ColorMap / Mixmap
*/
glActiveTextureARB( GL_TEXTURE0_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _texture0 );
glActiveTextureARB( GL_TEXTURE1_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _texture1 );
glActiveTextureARB( GL_TEXTURE2_ARB );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, _mixmap );
/*
unit0: COMBINE: TEX0 * TEX2_a + TEX1 * (1-TEX2_a)
*/
glActiveTextureARB( GL_TEXTURE0_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE2_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
/*
unit1: COMBINE: unit0 * TEX2_rgb
*/
glActiveTextureARB( GL_TEXTURE1_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE2_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
/*
unit2: MODULATE: unit1 * PRIMARY_COLOR
*/
glActiveTextureARB( GL_TEXTURE2_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );In my testbed app, it seems to work...
I get texture mixing, colormap application, and color interpolation between vertices. Seems right to me... I guess I'll put it in my game and cross my fingers.
It works! Explosions and laser blasts cause the terrain to light up!
Now, a new pickle. The per vertex shading on the terrain looks like hell -- and is essentially unnecessary due to my having a light/color map.
I'm going to have to fiddle and see if I can disable the primary lightsource without the terrain going black, but have it respond to the effects lighting.
Now, a new pickle. The per vertex shading on the terrain looks like hell -- and is essentially unnecessary due to my having a light/color map.
I'm going to have to fiddle and see if I can disable the primary lightsource without the terrain going black, but have it respond to the effects lighting.
That code looks fine. One thing is that the output alpha might be wrong, but that only matters if you're blending your terrain in multiple passes. You could use a constant env color to get 1.0 alpha on unit 1 if you need to.
So, yeah, it's up to you to figure out how to combine a diffuse colormap and GL's vertex lighting. If your colormap already has precalc'd shadows in it for the terrain, then maybe what you want is to ADD light in only for explosions. Figure out how to set up GL's lights so that all the terrain is black, except around an explosion. Then add PRIMARY_COLOR in unit3 instead of modulating.
Might look OK? There's no sure-fire solution, everything in graphics is approximations of approximations... so you have to dink around with it.
So, yeah, it's up to you to figure out how to combine a diffuse colormap and GL's vertex lighting. If your colormap already has precalc'd shadows in it for the terrain, then maybe what you want is to ADD light in only for explosions. Figure out how to set up GL's lights so that all the terrain is black, except around an explosion. Then add PRIMARY_COLOR in unit3 instead of modulating.
Might look OK? There's no sure-fire solution, everything in graphics is approximations of approximations... so you have to dink around with it.
Actually, I got it working and looking nice by having the terrain be rendered with only a mid-gray ambient light with specular and diffuse turned off. I get only the colormap lighting and dynamic lighting from lasers and explosions looks great.
arekkusu Wrote:Might look OK? There's no sure-fire solution, everything in graphics is approximations of approximations... so you have to dink around with it.
Yeah... I feel this pain. I spend waay too much time dinking with this stuff.
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| 2D Dynamic Lighting in OpenGL! Sort of... | metacollin | 22 | 15,557 |
Aug 19, 2009 01:48 AM Last Post: Madrayken |
|
| dynamic lighting problems | ghettotek | 3 | 2,433 |
Feb 15, 2003 07:05 PM Last Post: ghettotek |
|

