Using SubmergeTextures for Water & Lava
by Cisor · 03/29/2004 (11:04 am) · 0 comments
Ok, below follows a no bells-and-whistles resource to expose the existing lava functionality for water.
The resource assumes the following:
1) If you are using submerge textures, whatever colour you want is in the textures. Hence no background colour will be applied.
2) If you are using submergeTexture1, submergeTexture0 is also specified.
3) If no submergeTexture is specified (or it doesn't exist as specified in the waterblock) the default water/lava colour is used as hardcoded in game.cc.
Possible enhancements:
1) The ability to specify the background colour.
2) The ability to use both background color and textures.
3) The ability to use more than two textures.
4) Renaming the underlava.h and .cc to be something more meaningfull like submerge.h .cc.
In view of the TSE upgrade to the waterblock I didn't think it worthwhile to do the enhancements above, although they should be quite trivial to do.
First: BACK UP THE FOLLOWING FILES:
game.cc
underlava.h
underlava.cc
Second: In underlava.h,
find ...
and include the below after that...
then find...
and replace with...
Third: In underlava.cc,
find...
and comment out the whole routine, replacing it with the routine below...
As you can see I've commented the sections I've changed.
Fourth: In game.cc, in routine void GameRenderFilters(const CameraQuery& camq),
find...
and replace with...
Since game.cc is currently using the USEOLDFILTERS setting, that's actually is all that is required to make this work, but for sake of completeness, you can make the changes below as well to ensure that the NEWFILTERS section will also work.
Fifth: Still in game.cc, and routine void GameRenderFilters(const CameraQuery& camq),
find...
and after that insert...
Sixth: Still in game.cc, and routine void GameRenderFilters(const CameraQuery& camq),
find...
and comment it out...
Seventh and last: Still in game.cc, and routine void GameRenderFilters(const CameraQuery& camq),
find...
and replace with...
And that's it! Do a full-rebuild and you should be good to go.
PS: A note about the textures - make sure they wrap properly else you get unseemly seams.
Also, for water, blue or grayscale hazemaps work quite well.
Enjoy!
The resource assumes the following:
1) If you are using submerge textures, whatever colour you want is in the textures. Hence no background colour will be applied.
2) If you are using submergeTexture1, submergeTexture0 is also specified.
3) If no submergeTexture is specified (or it doesn't exist as specified in the waterblock) the default water/lava colour is used as hardcoded in game.cc.
Possible enhancements:
1) The ability to specify the background colour.
2) The ability to use both background color and textures.
3) The ability to use more than two textures.
4) Renaming the underlava.h and .cc to be something more meaningfull like submerge.h .cc.
In view of the TSE upgrade to the waterblock I didn't think it worthwhile to do the enhancements above, although they should be quite trivial to do.
First: BACK UP THE FOLLOWING FILES:
game.cc
underlava.h
underlava.cc
Second: In underlava.h,
find ...
#ifndef _MPOINT_H_ #include "math/mPoint.h" #endif
and include the below after that...
// included color - MJC #ifndef _COLOR_H_ #include "core/color.h" #endif
then find...
void render()
and replace with...
void render(ColorF color); // changed MJC to accept color
Third: In underlava.cc,
find...
void UnderLavaFX::render()
and comment out the whole routine, replacing it with the routine below...
void UnderLavaFX::render(ColorF color) // changed MJC to pass color
{
init();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
TextureHandle submergeTex = WaterBlock::getSubmergeTexture(0); // uncommented MJC
glBindTexture(GL_TEXTURE_2D, submergeTex.getGLName()); // changed MJC
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
glColor4f(color.red,color.green,color.blue,color.alpha); // changed MJC
// begin MJC to do submerge color
if(!submergeTex) {
glBegin(GL_TRIANGLE_FAN);
glVertex3f(-1, -1, 0);
glVertex3f(-1, 1, 0);
glVertex3f( 1, 1, 0);
glVertex3f( 1, -1, 0);
glEnd();
}
// end MJC
if( submergeTex ) // changed MJC
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// render layer 1
for( U32 i=0; i<mNumPoints.y; i++ )
{
renderRow( i, mNumPoints.y-1, mNumPoints.x-1 );
}
}
// give second layer a different phase
mWave[0].velocity += 10.0;
submergeTex = WaterBlock::getSubmergeTexture(1); // uncommented MJC
if( submergeTex ) // changed MJC
{
glBindTexture(GL_TEXTURE_2D, submergeTex.getGLName());
// render layer 2
for( U32 i=0; i<mNumPoints.y; i++ )
{
renderRow( i, mNumPoints.y-1, mNumPoints.x-1 );
}
}
glDepthMask(GL_TRUE);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}As you can see I've commented the sections I've changed.
Fourth: In game.cc, in routine void GameRenderFilters(const CameraQuery& camq),
find...
if (WaterBlock::isWater(WaterBlock::mSubmergedType))
{
// view filter for camera below the water surface
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glDisable(GL_TEXTURE_2D);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(.2, .6, .6, .3);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(-1, -1, 0);
glVertex3f(-1, 1, 0);
glVertex3f( 1, 1, 0);
glVertex3f( 1, -1, 0);
glEnd();
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
glDepthMask(GL_TRUE);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
else if (WaterBlock::isLava(WaterBlock::mSubmergedType))
{
gLavaFX.render();
}and replace with...
if (WaterBlock::isWater(WaterBlock::mSubmergedType))
{
// view filter for camera below the water surface
/* begin MJC
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glDisable(GL_TEXTURE_2D);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(.2, .6, .6, .3);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(-1, -1, 0);
glVertex3f(-1, 1, 0);
glVertex3f( 1, 1, 0);
glVertex3f( 1, -1, 0);
glEnd();
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
glDepthMask(GL_TRUE);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
end MJC */
// added MJC to send colour and use submerge textures
ColorF waterFilterColor(0.2, 0.6, 0.6, 0.6);
gLavaFX.render(waterFilterColor);
}
else if (WaterBlock::isLava(WaterBlock::mSubmergedType))
{
// added MJC to send lava colour
ColorF lavaFilterColor(1.0, 1.0, 1.0, 0.5);
gLavaFX.render(lavaFilterColor);
}Since game.cc is currently using the USEOLDFILTERS setting, that's actually is all that is required to make this work, but for sake of completeness, you can make the changes below as well to ensure that the NEWFILTERS section will also work.
Fifth: Still in game.cc, and routine void GameRenderFilters(const CameraQuery& camq),
find...
F32 invincible = 0.f; ColorF invincibleFilterColor(0.f, 0.f, 1.f, 0.f);
and after that insert...
ColorF lavaFilterColor(1.0, 1.0, 1.0, 0.5);
Sixth: Still in game.cc, and routine void GameRenderFilters(const CameraQuery& camq),
find...
if(addWaterFilter)
{
Xcolor = ( Xcolor * ( 1 - waterFilterColor.alpha ) ) + ( waterFilterColor * waterFilterColor.alpha );
Xcolor.alpha = Xcolor.alpha * ( 1 - waterFilterColor.alpha );
}and comment it out...
/* begin MJC
if(addWaterFilter)
{
Xcolor = ( Xcolor * ( 1 - waterFilterColor.alpha ) ) + ( waterFilterColor * waterFilterColor.alpha );
Xcolor.alpha = Xcolor.alpha * ( 1 - waterFilterColor.alpha );
}
end MJC */Seventh and last: Still in game.cc, and routine void GameRenderFilters(const CameraQuery& camq),
find...
// if were under lava, apply appropriate texture
if( addLavaFilter )
{
gLavaFX.render();
}and replace with...
// added MJC to use submerge textures for water and to
// send colour
if( addWaterFilter )
{
gLavaFX.render(waterFilterColor);
}
// end added MJC
// if were under lava, apply appropriate texture
if( addLavaFilter )
{
// changed MJC to send colour
gLavaFX.render(lavaFilterColor);
}And that's it! Do a full-rebuild and you should be good to go.
PS: A note about the textures - make sure they wrap properly else you get unseemly seams.
Also, for water, blue or grayscale hazemaps work quite well.
Enjoy!