diff options
author | Tim Angus <tim@ngus.net> | 2013-02-15 23:46:37 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-02-16 21:55:58 +0000 |
commit | 1fba10104e76e937eeac60bc207a74012ab936dc (patch) | |
tree | 7bcb5507cd1aa13e6f07b74c008e9391abbf26ae /src/renderer/tr_shade.c | |
parent | c1ad10c57be23f89f658a13729e4349b400a8734 (diff) |
renderer -> renderergl1, rend2 -> renderergl2
Diffstat (limited to 'src/renderer/tr_shade.c')
-rw-r--r-- | src/renderer/tr_shade.c | 1528 |
1 files changed, 0 insertions, 1528 deletions
diff --git a/src/renderer/tr_shade.c b/src/renderer/tr_shade.c deleted file mode 100644 index b8e8d268..00000000 --- a/src/renderer/tr_shade.c +++ /dev/null @@ -1,1528 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2009 Darklegion Development - -This file is part of Tremulous. - -Tremulous is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Tremulous is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Tremulous; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_shade.c - -#include "tr_local.h" -#if idppc_altivec && !defined(MACOS_X) -#include <altivec.h> -#endif - -/* - - THIS ENTIRE FILE IS BACK END - - This file deals with applying shaders to surface data in the tess struct. -*/ - -/* -================ -R_ArrayElementDiscrete - -This is just for OpenGL conformance testing, it should never be the fastest -================ -*/ -static void APIENTRY R_ArrayElementDiscrete( GLint index ) { - qglColor4ubv( tess.svars.colors[ index ] ); - if ( glState.currenttmu ) { - qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] ); - qglMultiTexCoord2fARB( 1, tess.svars.texcoords[ 1 ][ index ][0], tess.svars.texcoords[ 1 ][ index ][1] ); - } else { - qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] ); - } - qglVertex3fv( tess.xyz[ index ] ); -} - -/* -=================== -R_DrawStripElements - -=================== -*/ -static int c_vertexes; // for seeing how long our average strips are -static int c_begins; -static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) { - int i; - int last[3] = { -1, -1, -1 }; - qboolean even; - - c_begins++; - - if ( numIndexes <= 0 ) { - return; - } - - qglBegin( GL_TRIANGLE_STRIP ); - - // prime the strip - element( indexes[0] ); - element( indexes[1] ); - element( indexes[2] ); - c_vertexes += 3; - - last[0] = indexes[0]; - last[1] = indexes[1]; - last[2] = indexes[2]; - - even = qfalse; - - for ( i = 3; i < numIndexes; i += 3 ) - { - // odd numbered triangle in potential strip - if ( !even ) - { - // check previous triangle to see if we're continuing a strip - if ( ( indexes[i+0] == last[2] ) && ( indexes[i+1] == last[1] ) ) - { - element( indexes[i+2] ); - c_vertexes++; - assert( indexes[i+2] < tess.numVertexes ); - even = qtrue; - } - // otherwise we're done with this strip so finish it and start - // a new one - else - { - qglEnd(); - - qglBegin( GL_TRIANGLE_STRIP ); - c_begins++; - - element( indexes[i+0] ); - element( indexes[i+1] ); - element( indexes[i+2] ); - - c_vertexes += 3; - - even = qfalse; - } - } - else - { - // check previous triangle to see if we're continuing a strip - if ( ( last[2] == indexes[i+1] ) && ( last[0] == indexes[i+0] ) ) - { - element( indexes[i+2] ); - c_vertexes++; - - even = qfalse; - } - // otherwise we're done with this strip so finish it and start - // a new one - else - { - qglEnd(); - - qglBegin( GL_TRIANGLE_STRIP ); - c_begins++; - - element( indexes[i+0] ); - element( indexes[i+1] ); - element( indexes[i+2] ); - c_vertexes += 3; - - even = qfalse; - } - } - - // cache the last three vertices - last[0] = indexes[i+0]; - last[1] = indexes[i+1]; - last[2] = indexes[i+2]; - } - - qglEnd(); -} - - - -/* -================== -R_DrawElements - -Optionally performs our own glDrawElements that looks for strip conditions -instead of using the single glDrawElements call that may be inefficient -without compiled vertex arrays. -================== -*/ -static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) { - int primitives; - - primitives = r_primitives->integer; - - // default is to use triangles if compiled vertex arrays are present - if ( primitives == 0 ) { - if ( qglLockArraysEXT ) { - primitives = 2; - } else { - primitives = 1; - } - } - - - if ( primitives == 2 ) { - qglDrawElements( GL_TRIANGLES, - numIndexes, - GL_INDEX_TYPE, - indexes ); - return; - } - - if ( primitives == 1 ) { - R_DrawStripElements( numIndexes, indexes, qglArrayElement ); - return; - } - - if ( primitives == 3 ) { - R_DrawStripElements( numIndexes, indexes, R_ArrayElementDiscrete ); - return; - } - - // anything else will cause no drawing -} - - -/* -============================================================= - -SURFACE SHADERS - -============================================================= -*/ - -shaderCommands_t tess; -static qboolean setArraysOnce; - -/* -================= -R_BindAnimatedImage - -================= -*/ -static void R_BindAnimatedImage( textureBundle_t *bundle ) { - int index; - - if ( bundle->isVideoMap ) { - ri.CIN_RunCinematic(bundle->videoMapHandle); - ri.CIN_UploadCinematic(bundle->videoMapHandle); - return; - } - - if ( bundle->numImageAnimations <= 1 ) { - GL_Bind( bundle->image[0] ); - return; - } - - // it is necessary to do this messy calc to make sure animations line up - // exactly with waveforms of the same frequency - index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE); - index >>= FUNCTABLE_SIZE2; - - if ( index < 0 ) { - index = 0; // may happen with shader time offsets - } - index %= bundle->numImageAnimations; - - GL_Bind( bundle->image[ index ] ); -} - -/* -================ -DrawTris - -Draws triangle outlines for debugging -================ -*/ -static void DrawTris (shaderCommands_t *input) { - GL_Bind( tr.whiteImage ); - qglColor3f (1,1,1); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); - qglDepthRange( 0, 0 ); - - qglDisableClientState (GL_COLOR_ARRAY); - qglDisableClientState (GL_TEXTURE_COORD_ARRAY); - - qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD - - if (qglLockArraysEXT) { - qglLockArraysEXT(0, input->numVertexes); - GLimp_LogComment( "glLockArraysEXT\n" ); - } - - R_DrawElements( input->numIndexes, input->indexes ); - - if (qglUnlockArraysEXT) { - qglUnlockArraysEXT(); - GLimp_LogComment( "glUnlockArraysEXT\n" ); - } - qglDepthRange( 0, 1 ); -} - - -/* -================ -DrawNormals - -Draws vertex normals for debugging -================ -*/ -static void DrawNormals (shaderCommands_t *input) { - int i; - vec3_t temp; - - GL_Bind( tr.whiteImage ); - qglColor3f (1,1,1); - qglDepthRange( 0, 0 ); // never occluded - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); - - qglBegin (GL_LINES); - for (i = 0 ; i < input->numVertexes ; i++) { - qglVertex3fv (input->xyz[i]); - VectorMA (input->xyz[i], 2, input->normal[i], temp); - qglVertex3fv (temp); - } - qglEnd (); - - qglDepthRange( 0, 1 ); -} - -/* -============== -RB_BeginSurface - -We must set some things up before beginning any tesselation, -because a surface may be forced to perform a RB_End due -to overflow. -============== -*/ -void RB_BeginSurface( shader_t *shader, int fogNum ) { - - shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader; - - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.shader = state; - tess.fogNum = fogNum; - tess.dlightBits = 0; // will be OR'd in by surface functions - tess.xstages = state->stages; - tess.numPasses = state->numUnfoggedPasses; - tess.currentStageIteratorFunc = state->optimalStageIteratorFunc; - - tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) { - tess.shaderTime = tess.shader->clampTime; - } - - -} - -/* -=================== -DrawMultitextured - -output = t0 * t1 or t0 + t1 - -t0 = most upstream according to spec -t1 = most downstream according to spec -=================== -*/ -static void DrawMultitextured( shaderCommands_t *input, int stage ) { - shaderStage_t *pStage; - - pStage = tess.xstages[stage]; - - GL_State( pStage->stateBits ); - - // this is an ugly hack to work around a GeForce driver - // bug with multitexture and clip planes - if ( backEnd.viewParms.isPortal ) { - qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - - // - // base - // - GL_SelectTexture( 0 ); - qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); - R_BindAnimatedImage( &pStage->bundle[0] ); - - // - // lightmap/secondary pass - // - GL_SelectTexture( 1 ); - qglEnable( GL_TEXTURE_2D ); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - if ( r_lightmap->integer ) { - GL_TexEnv( GL_REPLACE ); - } else { - GL_TexEnv( tess.shader->multitextureEnv ); - } - - qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[1] ); - - R_BindAnimatedImage( &pStage->bundle[1] ); - - R_DrawElements( input->numIndexes, input->indexes ); - - // - // disable texturing on TEXTURE1, then select TEXTURE0 - // - //qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - qglDisable( GL_TEXTURE_2D ); - - GL_SelectTexture( 0 ); -} - - - -/* -=================== -ProjectDlightTexture - -Perform dynamic lighting with another rendering pass -=================== -*/ -#if idppc_altivec -static void ProjectDlightTexture_altivec( void ) { - int i, l; - vec_t origin0, origin1, origin2; - float texCoords0, texCoords1; - vector float floatColorVec0, floatColorVec1; - vector float modulateVec, colorVec, zero; - vector short colorShort; - vector signed int colorInt; - vector unsigned char floatColorVecPerm, modulatePerm, colorChar; - vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff); - float *texCoords; - byte *colors; - byte clipBits[SHADER_MAX_VERTEXES]; - float texCoordsArray[SHADER_MAX_VERTEXES][2]; - byte colorArray[SHADER_MAX_VERTEXES][4]; - unsigned hitIndexes[SHADER_MAX_INDEXES]; - int numIndexes; - float scale; - float radius; - vec3_t floatColor; - float modulate = 0.0f; - - if ( !backEnd.refdef.num_dlights ) { - return; - } - - // There has to be a better way to do this so that floatColor - // and/or modulate are already 16-byte aligned. - floatColorVecPerm = vec_lvsl(0,(float *)floatColor); - modulatePerm = vec_lvsl(0,(float *)&modulate); - modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0); - zero = (vector float)vec_splat_s8(0); - - for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { - dlight_t *dl; - - if ( !( tess.dlightBits & ( 1 << l ) ) ) { - continue; // this surface definately doesn't have any of this light - } - texCoords = texCoordsArray[0]; - colors = colorArray[0]; - - dl = &backEnd.refdef.dlights[l]; - origin0 = dl->transformed[0]; - origin1 = dl->transformed[1]; - origin2 = dl->transformed[2]; - radius = dl->radius; - scale = 1.0f / radius; - - if(r_greyscale->integer) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = floatColor[1] = floatColor[2] = luminance; - } - else if(r_greyscale->value) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); - floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); - floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); - } - else - { - floatColor[0] = dl->color[0] * 255.0f; - floatColor[1] = dl->color[1] * 255.0f; - floatColor[2] = dl->color[2] * 255.0f; - } - floatColorVec0 = vec_ld(0, floatColor); - floatColorVec1 = vec_ld(11, floatColor); - floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm); - for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { - int clip = 0; - vec_t dist0, dist1, dist2; - - dist0 = origin0 - tess.xyz[i][0]; - dist1 = origin1 - tess.xyz[i][1]; - dist2 = origin2 - tess.xyz[i][2]; - - backEnd.pc.c_dlightVertexes++; - - texCoords0 = 0.5f + dist0 * scale; - texCoords1 = 0.5f + dist1 * scale; - - if( !r_dlightBacks->integer && - // dist . tess.normal[i] - ( dist0 * tess.normal[i][0] + - dist1 * tess.normal[i][1] + - dist2 * tess.normal[i][2] ) < 0.0f ) { - clip = 63; - } else { - if ( texCoords0 < 0.0f ) { - clip |= 1; - } else if ( texCoords0 > 1.0f ) { - clip |= 2; - } - if ( texCoords1 < 0.0f ) { - clip |= 4; - } else if ( texCoords1 > 1.0f ) { - clip |= 8; - } - texCoords[0] = texCoords0; - texCoords[1] = texCoords1; - - // modulate the strength based on the height and color - if ( dist2 > radius ) { - clip |= 16; - modulate = 0.0f; - } else if ( dist2 < -radius ) { - clip |= 32; - modulate = 0.0f; - } else { - dist2 = Q_fabs(dist2); - if ( dist2 < radius * 0.5f ) { - modulate = 1.0f; - } else { - modulate = 2.0f * (radius - dist2) * scale; - } - } - } - clipBits[i] = clip; - - modulateVec = vec_ld(0,(float *)&modulate); - modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm); - colorVec = vec_madd(floatColorVec0,modulateVec,zero); - colorInt = vec_cts(colorVec,0); // RGBx - colorShort = vec_pack(colorInt,colorInt); // RGBxRGBx - colorChar = vec_packsu(colorShort,colorShort); // RGBxRGBxRGBxRGBx - colorChar = vec_sel(colorChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255 - vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors); // store color - } - - // build a list of triangles that need light - numIndexes = 0; - for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { - int a, b, c; - - a = tess.indexes[i]; - b = tess.indexes[i+1]; - c = tess.indexes[i+2]; - if ( clipBits[a] & clipBits[b] & clipBits[c] ) { - continue; // not lighted - } - hitIndexes[numIndexes] = a; - hitIndexes[numIndexes+1] = b; - hitIndexes[numIndexes+2] = c; - numIndexes += 3; - } - - if ( !numIndexes ) { - continue; - } - - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); - - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); - - GL_Bind( tr.dlightImage ); - // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light - // where they aren't rendered - if ( dl->additive ) { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - else { - GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - R_DrawElements( numIndexes, hitIndexes ); - backEnd.pc.c_totalIndexes += numIndexes; - backEnd.pc.c_dlightIndexes += numIndexes; - } -} -#endif - - -static void ProjectDlightTexture_scalar( void ) { - int i, l; - vec3_t origin; - float *texCoords; - byte *colors; - byte clipBits[SHADER_MAX_VERTEXES]; - float texCoordsArray[SHADER_MAX_VERTEXES][2]; - byte colorArray[SHADER_MAX_VERTEXES][4]; - unsigned hitIndexes[SHADER_MAX_INDEXES]; - int numIndexes; - float scale; - float radius; - vec3_t floatColor; - float modulate = 0.0f; - - if ( !backEnd.refdef.num_dlights ) { - return; - } - - for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { - dlight_t *dl; - - if ( !( tess.dlightBits & ( 1 << l ) ) ) { - continue; // this surface definately doesn't have any of this light - } - texCoords = texCoordsArray[0]; - colors = colorArray[0]; - - dl = &backEnd.refdef.dlights[l]; - VectorCopy( dl->transformed, origin ); - radius = dl->radius; - scale = 1.0f / radius; - - if(r_greyscale->integer) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = floatColor[1] = floatColor[2] = luminance; - } - else if(r_greyscale->value) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); - floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); - floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); - } - else - { - floatColor[0] = dl->color[0] * 255.0f; - floatColor[1] = dl->color[1] * 255.0f; - floatColor[2] = dl->color[2] * 255.0f; - } - - for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { - int clip = 0; - vec3_t dist; - - VectorSubtract( origin, tess.xyz[i], dist ); - - backEnd.pc.c_dlightVertexes++; - - texCoords[0] = 0.5f + dist[0] * scale; - texCoords[1] = 0.5f + dist[1] * scale; - - if( !r_dlightBacks->integer && - // dist . tess.normal[i] - ( dist[0] * tess.normal[i][0] + - dist[1] * tess.normal[i][1] + - dist[2] * tess.normal[i][2] ) < 0.0f ) { - clip = 63; - } else { - if ( texCoords[0] < 0.0f ) { - clip |= 1; - } else if ( texCoords[0] > 1.0f ) { - clip |= 2; - } - if ( texCoords[1] < 0.0f ) { - clip |= 4; - } else if ( texCoords[1] > 1.0f ) { - clip |= 8; - } - texCoords[0] = texCoords[0]; - texCoords[1] = texCoords[1]; - - // modulate the strength based on the height and color - if ( dist[2] > radius ) { - clip |= 16; - modulate = 0.0f; - } else if ( dist[2] < -radius ) { - clip |= 32; - modulate = 0.0f; - } else { - dist[2] = Q_fabs(dist[2]); - if ( dist[2] < radius * 0.5f ) { - modulate = 1.0f; - } else { - modulate = 2.0f * (radius - dist[2]) * scale; - } - } - } - clipBits[i] = clip; - colors[0] = ri.ftol(floatColor[0] * modulate); - colors[1] = ri.ftol(floatColor[1] * modulate); - colors[2] = ri.ftol(floatColor[2] * modulate); - colors[3] = 255; - } - - // build a list of triangles that need light - numIndexes = 0; - for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { - int a, b, c; - - a = tess.indexes[i]; - b = tess.indexes[i+1]; - c = tess.indexes[i+2]; - if ( clipBits[a] & clipBits[b] & clipBits[c] ) { - continue; // not lighted - } - hitIndexes[numIndexes] = a; - hitIndexes[numIndexes+1] = b; - hitIndexes[numIndexes+2] = c; - numIndexes += 3; - } - - if ( !numIndexes ) { - continue; - } - - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); - - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); - - GL_Bind( tr.dlightImage ); - // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light - // where they aren't rendered - if ( dl->additive ) { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - else { - GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - R_DrawElements( numIndexes, hitIndexes ); - backEnd.pc.c_totalIndexes += numIndexes; - backEnd.pc.c_dlightIndexes += numIndexes; - } -} - -static void ProjectDlightTexture( void ) { -#if idppc_altivec - if (com_altivec->integer) { - // must be in a seperate function or G3 systems will crash. - ProjectDlightTexture_altivec(); - return; - } -#endif - ProjectDlightTexture_scalar(); -} - - -/* -=================== -RB_FogPass - -Blends a fog texture on top of everything else -=================== -*/ -static void RB_FogPass( void ) { - fog_t *fog; - int i; - - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); - - qglEnableClientState( GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); - - fog = tr.world->fogs + tess.fogNum; - - for ( i = 0; i < tess.numVertexes; i++ ) { - * ( int * )&tess.svars.colors[i] = fog->colorInt; - } - - RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] ); - - GL_Bind( tr.fogImage ); - - if ( tess.shader->fogPass == FP_EQUAL ) { - GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); - } else { - GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - } - - R_DrawElements( tess.numIndexes, tess.indexes ); -} - -/* -=============== -ComputeColors -=============== -*/ -static void ComputeColors( shaderStage_t *pStage ) -{ - int i; - - // - // rgbGen - // - switch ( pStage->rgbGen ) - { - case CGEN_IDENTITY: - Com_Memset( tess.svars.colors, 0xff, tess.numVertexes * 4 ); - break; - default: - case CGEN_IDENTITY_LIGHTING: - Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); - break; - case CGEN_LIGHTING_DIFFUSE: - RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); - break; - case CGEN_EXACT_VERTEX: - Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); - break; - case CGEN_CONST: - for ( i = 0; i < tess.numVertexes; i++ ) { - *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; - } - break; - case CGEN_VERTEX: - if ( tr.identityLight == 1 ) - { - Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); - } - else - { - for ( i = 0; i < tess.numVertexes; i++ ) - { - tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight; - tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight; - tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight; - tess.svars.colors[i][3] = tess.vertexColors[i][3]; - } - } - break; - case CGEN_ONE_MINUS_VERTEX: - if ( tr.identityLight == 1 ) - { - for ( i = 0; i < tess.numVertexes; i++ ) - { - tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0]; - tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1]; - tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2]; - } - } - else - { - for ( i = 0; i < tess.numVertexes; i++ ) - { - tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight; - tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight; - tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight; - } - } - break; - case CGEN_FOG: - { - fog_t *fog; - - fog = tr.world->fogs + tess.fogNum; - - for ( i = 0; i < tess.numVertexes; i++ ) { - * ( int * )&tess.svars.colors[i] = fog->colorInt; - } - } - break; - case CGEN_WAVEFORM: - RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors ); - break; - case CGEN_ENTITY: - RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors ); - break; - case CGEN_ONE_MINUS_ENTITY: - RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); - break; - } - - // - // alphaGen - // - switch ( pStage->alphaGen ) - { - case AGEN_SKIP: - break; - case AGEN_IDENTITY: - if ( pStage->rgbGen != CGEN_IDENTITY ) { - if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) || - pStage->rgbGen != CGEN_VERTEX ) { - for ( i = 0; i < tess.numVertexes; i++ ) { - tess.svars.colors[i][3] = 0xff; - } - } - } - break; - case AGEN_CONST: - if ( pStage->rgbGen != CGEN_CONST ) { - for ( i = 0; i < tess.numVertexes; i++ ) { - tess.svars.colors[i][3] = pStage->constantColor[3]; - } - } - break; - case AGEN_WAVEFORM: - RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors ); - break; - case AGEN_LIGHTING_SPECULAR: - RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors ); - break; - case AGEN_ENTITY: - RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors ); - break; - case AGEN_ONE_MINUS_ENTITY: - RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); - break; - case AGEN_VERTEX: - if ( pStage->rgbGen != CGEN_VERTEX ) { - for ( i = 0; i < tess.numVertexes; i++ ) { - tess.svars.colors[i][3] = tess.vertexColors[i][3]; - } - } - break; - case AGEN_ONE_MINUS_VERTEX: - for ( i = 0; i < tess.numVertexes; i++ ) - { - tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3]; - } - break; - case AGEN_PORTAL: - { - unsigned char alpha; - - for ( i = 0; i < tess.numVertexes; i++ ) - { - float len; - vec3_t v; - - VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v ); - len = VectorLength( v ); - - len /= tess.shader->portalRange; - - if ( len < 0 ) - { - alpha = 0; - } - else if ( len > 1 ) - { - alpha = 0xff; - } - else - { - alpha = len * 0xff; - } - - tess.svars.colors[i][3] = alpha; - } - } - break; - } - - // - // fog adjustment for colors to fade out as fog increases - // - if ( tess.fogNum ) - { - switch ( pStage->adjustColorsForFog ) - { - case ACFF_MODULATE_RGB: - RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors ); - break; - case ACFF_MODULATE_ALPHA: - RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors ); - break; - case ACFF_MODULATE_RGBA: - RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors ); - break; - case ACFF_NONE: - break; - } - } - - // if in greyscale rendering mode turn all color values into greyscale. - if(r_greyscale->integer) - { - int scale; - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } - } - else if(r_greyscale->value) - { - float scale; - - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = LERP(tess.svars.colors[i][0], scale, r_greyscale->value); - tess.svars.colors[i][1] = LERP(tess.svars.colors[i][1], scale, r_greyscale->value); - tess.svars.colors[i][2] = LERP(tess.svars.colors[i][2], scale, r_greyscale->value); - } - } -} - -/* -=============== -ComputeTexCoords -=============== -*/ -static void ComputeTexCoords( shaderStage_t *pStage ) { - int i; - int b; - - for ( b = 0; b < NUM_TEXTURE_BUNDLES; b++ ) { - int tm; - - // - // generate the texture coordinates - // - switch ( pStage->bundle[b].tcGen ) - { - case TCGEN_IDENTITY: - Com_Memset( tess.svars.texcoords[b], 0, sizeof( float ) * 2 * tess.numVertexes ); - break; - case TCGEN_TEXTURE: - for ( i = 0 ; i < tess.numVertexes ; i++ ) { - tess.svars.texcoords[b][i][0] = tess.texCoords[i][0][0]; - tess.svars.texcoords[b][i][1] = tess.texCoords[i][0][1]; - } - break; - case TCGEN_LIGHTMAP: - for ( i = 0 ; i < tess.numVertexes ; i++ ) { - tess.svars.texcoords[b][i][0] = tess.texCoords[i][1][0]; - tess.svars.texcoords[b][i][1] = tess.texCoords[i][1][1]; - } - break; - case TCGEN_VECTOR: - for ( i = 0 ; i < tess.numVertexes ; i++ ) { - tess.svars.texcoords[b][i][0] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[0] ); - tess.svars.texcoords[b][i][1] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[1] ); - } - break; - case TCGEN_FOG: - RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[b] ); - break; - case TCGEN_ENVIRONMENT_MAPPED: - RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] ); - break; - case TCGEN_BAD: - return; - } - - // - // alter texture coordinates - // - for ( tm = 0; tm < pStage->bundle[b].numTexMods ; tm++ ) { - switch ( pStage->bundle[b].texMods[tm].type ) - { - case TMOD_NONE: - tm = TR_MAX_TEXMODS; // break out of for loop - break; - - case TMOD_TURBULENT: - RB_CalcTurbulentTexCoords( &pStage->bundle[b].texMods[tm].wave, - ( float * ) tess.svars.texcoords[b] ); - break; - - case TMOD_ENTITY_TRANSLATE: - RB_CalcScrollTexCoords( backEnd.currentEntity->e.shaderTexCoord, - ( float * ) tess.svars.texcoords[b] ); - break; - - case TMOD_SCROLL: - RB_CalcScrollTexCoords( pStage->bundle[b].texMods[tm].scroll, - ( float * ) tess.svars.texcoords[b] ); - break; - - case TMOD_SCALE: - RB_CalcScaleTexCoords( pStage->bundle[b].texMods[tm].scale, - ( float * ) tess.svars.texcoords[b] ); - break; - - case TMOD_STRETCH: - RB_CalcStretchTexCoords( &pStage->bundle[b].texMods[tm].wave, - ( float * ) tess.svars.texcoords[b] ); - break; - - case TMOD_TRANSFORM: - RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm], - ( float * ) tess.svars.texcoords[b] ); - break; - - case TMOD_ROTATE: - RB_CalcRotateTexCoords( pStage->bundle[b].texMods[tm].rotateSpeed, - ( float * ) tess.svars.texcoords[b] ); - break; - - default: - ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", pStage->bundle[b].texMods[tm].type, tess.shader->name ); - break; - } - } - } -} - -/* -** RB_IterateStagesGeneric -*/ -static void RB_IterateStagesGeneric( shaderCommands_t *input ) -{ - int stage; - - for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) - { - shaderStage_t *pStage = tess.xstages[stage]; - - if ( !pStage ) - { - break; - } - - ComputeColors( pStage ); - ComputeTexCoords( pStage ); - - if ( !setArraysOnce ) - { - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); - } - - // - // do multitexture - // - if ( pStage->bundle[1].image[0] != 0 ) - { - DrawMultitextured( input, stage ); - } - else - { - if ( !setArraysOnce ) - { - qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); - } - - // - // set state - // - if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) - { - GL_Bind( tr.whiteImage ); - } - else - R_BindAnimatedImage( &pStage->bundle[0] ); - - GL_State( pStage->stateBits ); - - // - // draw - // - R_DrawElements( input->numIndexes, input->indexes ); - } - // allow skipping out to show just lightmaps during development - if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) - { - break; - } - } -} - - -/* -** RB_StageIteratorGeneric -*/ -void RB_StageIteratorGeneric( void ) -{ - shaderCommands_t *input; - shader_t *shader; - - input = &tess; - shader = input->shader; - - RB_DeformTessGeometry(); - - // - // log this call - // - if ( r_logFile->integer ) - { - // don't just call LogComment, or we will get - // a call to va() every frame! - GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name) ); - } - - // - // set face culling appropriately - // - GL_Cull( shader->cullType ); - - // set polygon offset if necessary - if ( shader->polygonOffset ) - { - qglEnable( GL_POLYGON_OFFSET_FILL ); - qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); - } - - // - // if there is only a single pass then we can enable color - // and texture arrays before we compile, otherwise we need - // to avoid compiling those arrays since they will change - // during multipass rendering - // - if ( tess.numPasses > 1 || shader->multitextureEnv ) - { - setArraysOnce = qfalse; - qglDisableClientState (GL_COLOR_ARRAY); - qglDisableClientState (GL_TEXTURE_COORD_ARRAY); - } - else - { - setArraysOnce = qtrue; - - qglEnableClientState( GL_COLOR_ARRAY); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); - - qglEnableClientState( GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); - } - - // - // lock XYZ - // - qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD - if (qglLockArraysEXT) - { - qglLockArraysEXT(0, input->numVertexes); - GLimp_LogComment( "glLockArraysEXT\n" ); - } - - // - // enable color and texcoord arrays after the lock if necessary - // - if ( !setArraysOnce ) - { - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglEnableClientState( GL_COLOR_ARRAY ); - } - - // - // call shader function - // - RB_IterateStagesGeneric( input ); - - // - // now do any dynamic lighting needed - // - if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE - && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) { - ProjectDlightTexture(); - } - - // - // now do fog - // - if ( tess.fogNum && tess.shader->fogPass ) { - RB_FogPass(); - } - - // - // unlock arrays - // - if (qglUnlockArraysEXT) - { - qglUnlockArraysEXT(); - GLimp_LogComment( "glUnlockArraysEXT\n" ); - } - - // - // reset polygon offset - // - if ( shader->polygonOffset ) - { - qglDisable( GL_POLYGON_OFFSET_FILL ); - } -} - - -/* -** RB_StageIteratorVertexLitTexture -*/ -void RB_StageIteratorVertexLitTexture( void ) -{ - shaderCommands_t *input; - shader_t *shader; - - input = &tess; - shader = input->shader; - - // - // compute colors - // - RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); - - // - // log this call - // - if ( r_logFile->integer ) - { - // don't just call LogComment, or we will get - // a call to va() every frame! - GLimp_LogComment( va("--- RB_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess.shader->name) ); - } - - // - // set face culling appropriately - // - GL_Cull( shader->cullType ); - - // - // set arrays and lock - // - qglEnableClientState( GL_COLOR_ARRAY); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY); - - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); - qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); - qglVertexPointer (3, GL_FLOAT, 16, input->xyz); - - if ( qglLockArraysEXT ) - { - qglLockArraysEXT(0, input->numVertexes); - GLimp_LogComment( "glLockArraysEXT\n" ); - } - - // - // call special shade routine - // - R_BindAnimatedImage( &tess.xstages[0]->bundle[0] ); - GL_State( tess.xstages[0]->stateBits ); - R_DrawElements( input->numIndexes, input->indexes ); - - // - // now do any dynamic lighting needed - // - if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) { - ProjectDlightTexture(); - } - - // - // now do fog - // - if ( tess.fogNum && tess.shader->fogPass ) { - RB_FogPass(); - } - - // - // unlock arrays - // - if (qglUnlockArraysEXT) - { - qglUnlockArraysEXT(); - GLimp_LogComment( "glUnlockArraysEXT\n" ); - } -} - -//define REPLACE_MODE - -void RB_StageIteratorLightmappedMultitexture( void ) { - shaderCommands_t *input; - shader_t *shader; - - input = &tess; - shader = input->shader; - - // - // log this call - // - if ( r_logFile->integer ) { - // don't just call LogComment, or we will get - // a call to va() every frame! - GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name) ); - } - - // - // set face culling appropriately - // - GL_Cull( shader->cullType ); - - // - // set color, pointers, and lock - // - GL_State( GLS_DEFAULT ); - qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); - -#ifdef REPLACE_MODE - qglDisableClientState( GL_COLOR_ARRAY ); - qglColor3f( 1, 1, 1 ); - qglShadeModel( GL_FLAT ); -#else - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 ); -#endif - - // - // select base stage - // - GL_SelectTexture( 0 ); - - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - R_BindAnimatedImage( &tess.xstages[0]->bundle[0] ); - qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); - - // - // configure second stage - // - GL_SelectTexture( 1 ); - qglEnable( GL_TEXTURE_2D ); - if ( r_lightmap->integer ) { - GL_TexEnv( GL_REPLACE ); - } else { - GL_TexEnv( GL_MODULATE ); - } - R_BindAnimatedImage( &tess.xstages[0]->bundle[1] ); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] ); - - // - // lock arrays - // - if ( qglLockArraysEXT ) { - qglLockArraysEXT(0, input->numVertexes); - GLimp_LogComment( "glLockArraysEXT\n" ); - } - - R_DrawElements( input->numIndexes, input->indexes ); - - // - // disable texturing on TEXTURE1, then select TEXTURE0 - // - qglDisable( GL_TEXTURE_2D ); - qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - - GL_SelectTexture( 0 ); -#ifdef REPLACE_MODE - GL_TexEnv( GL_MODULATE ); - qglShadeModel( GL_SMOOTH ); -#endif - - // - // now do any dynamic lighting needed - // - if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) { - ProjectDlightTexture(); - } - - // - // now do fog - // - if ( tess.fogNum && tess.shader->fogPass ) { - RB_FogPass(); - } - - // - // unlock arrays - // - if ( qglUnlockArraysEXT ) { - qglUnlockArraysEXT(); - GLimp_LogComment( "glUnlockArraysEXT\n" ); - } -} - -/* -** RB_EndSurface -*/ -void RB_EndSurface( void ) { - shaderCommands_t *input; - - input = &tess; - - if (input->numIndexes == 0) { - return; - } - - if (input->indexes[SHADER_MAX_INDEXES-1] != 0) { - ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit"); - } - if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) { - ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit"); - } - - if ( tess.shader == tr.shadowShader ) { - RB_ShadowTessEnd(); - return; - } - - // for debugging of sort order issues, stop rendering after a given sort value - if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) { - return; - } - - // - // update performance counters - // - backEnd.pc.c_shaders++; - backEnd.pc.c_vertexes += tess.numVertexes; - backEnd.pc.c_indexes += tess.numIndexes; - backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses; - - // - // call off to shader specific tess end function - // - tess.currentStageIteratorFunc(); - - // - // draw debugging stuff - // - if ( r_showtris->integer ) { - DrawTris (input); - } - if ( r_shownormals->integer ) { - DrawNormals (input); - } - // clear shader so we can tell we don't have any unclosed surfaces - tess.numIndexes = 0; - - GLimp_LogComment( "----------\n" ); -} - |