1
0
forked from 0ad/0ad

Alternative player-colour rendering, which probably works with lights

This was SVN commit r1792.
This commit is contained in:
Ykkrosh 2005-01-23 22:02:36 +00:00
parent 6fa79e0247
commit 225446d648
2 changed files with 85 additions and 72 deletions

View File

@ -803,90 +803,103 @@ void CRenderer::RenderModelSubmissions()
if (! playercolor)
{
// pass one through as alpha; transparent textures handled specially by CTransparencyRenderer
// (gl_constant means the colour comes from the environment (glColorxf))
// TODO: ^^^ no it doesn't (I (Philip) think) - gl_primary_color comes from
// glColorxf, gl_constant comes from gl_texture_env_color. Unless I'm
// mistaken.
// (gl_constant means the colour comes from the gl_texture_env_color)
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
float color[] = { 1.0, 1.0, 1.0, 1.0 };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
// setup client states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
// render models
CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0);
// switch off client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
else
{
// Render two passes: first, render the unit as normal. Second,
// render it again but modulated with the player-colour, using
// the alpha channel as a mask.
//
// Assume the alpha channel is 1-bit, so there's no need for blending.
//
// This probably ought to be done in a single pass on hardware that
// supports register combiners / fragment programs / etc.
float color[] = { 1.0, 0.0, 0.0, 1.0 };
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}
else
{
// Pass through the alpha to the second texture unit
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
// Second texture unit:
//
// output = texture*alpha + playercolour*(1-alpha)
//
// where playercolour = previous stage, texture = colour from texture,
// alpha = alpha from texture. Do this using GL_INTERPOLATE, which
// performs precisely that calculation.
glDisable(GL_ALPHA_TEST);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
// Set the proper LOD bias
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, m_Options.m_LodBias);
// Set this texture unit to calculate arg0*arg2 + arg1*(1-arg2)
// using 'interpolate'
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
// arg0 = texture
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
// TODO: GL_TEXTURE0 requires ARB_texture_env_crossbar, or OpenGL 1.4.
// Will that be a problem? Can it be avoided?
// arg1 = player-colour modulated texture, from previous render stage
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
// arg2 = texture alpha, from previous render stage
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
// Set the alpha to be 1.0 (obtained from the environment colour)
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}
// setup client states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (!playercolor)
glEnableClientState(GL_COLOR_ARRAY);
if (playercolor)
// TODO: nicer color
glColor4f(1.0, 0.0, 0.0, 1.0);
// render models
if (playercolor)
CModelRData::RenderModels(STREAM_POS|STREAM_UV0);
else
// Render first pass
CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0);
// switch off client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (! playercolor)
glDisableClientState(GL_COLOR_ARRAY);
// Set up second pass: first texture unit carries on doing texture*lighting,
// but passes alpha through inverted; the second texture unit modulates
// with the player colour.
if (playercolor)
{
glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
// t1 = t0 * playercolor
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
// Continue passing through alpha from texture
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
// Only render high-alpha parts
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.5f);
// Render second pass
CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0);
// Restore states
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glActiveTexture(GL_TEXTURE0);
// switch off client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
}

View File

@ -53,7 +53,7 @@ void CTransparencyRenderer::Render()
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
// just pass through texture's alpha