From 5b141089c3d45973762a9355e4b0ed11da73821c Mon Sep 17 00:00:00 2001 From: OM Date: Mon, 15 May 2023 20:14:45 +0200 Subject: [PATCH] Added support for a few colorGen_t and alphaGen_t values --- code/renderer/tr_local.h | 20 ++-- code/renderer/tr_shade.c | 192 +++++++++++++++++++++++++--------- code/renderer/tr_shade_calc.c | 76 ++++++++++++-- code/renderer/tr_shader.c | 68 +++++++----- 4 files changed, 263 insertions(+), 93 deletions(-) diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h index 2cf474aa..62ef2995 100644 --- a/code/renderer/tr_local.h +++ b/code/renderer/tr_local.h @@ -231,6 +231,7 @@ typedef struct image_s { typedef enum { SS_BAD, SS_PORTAL, // mirrors, portals, viewscreens + SS_PORTALSKY, SS_ENVIRONMENT, // sky box SS_OPAQUE, // opaque @@ -239,8 +240,6 @@ typedef enum { // in addition to alpha test SS_BANNER, - SS_FOG, - SS_UNDERWATER, // for items that should be drawn in front of the water plane SS_BLEND0, // regular transparency and filters @@ -336,10 +335,7 @@ typedef enum { CGEN_SCOORD, CGEN_TCOORD, CGEN_DOT, - CGEN_ONE_MINUS_DOT, - CGEN_LIGHTING_DIFFUSE, - CGEN_FOG, // standard fog - CGEN_CONST // fixed color + CGEN_ONE_MINUS_DOT } colorGen_t; typedef enum { @@ -2079,13 +2075,21 @@ void RB_CalcModulateColorsByFog( unsigned char *dstColors ); void RB_CalcModulateAlphasByFog( unsigned char *dstColors ); void RB_CalcModulateRGBAsByFog( unsigned char *dstColors ); void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors ); -void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ); +void RB_CalcWaveColor(const waveForm_t* wf, unsigned char* dstColors, unsigned char* constantColor); void RB_CalcAlphaFromEntity( unsigned char *dstColors ); void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ); void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords ); void RB_CalcColorFromEntity( unsigned char *dstColors ); void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ); -void RB_CalcSpecularAlpha( unsigned char *alphas ); +void RB_CalcColorFromConstant(unsigned char* dstColors, unsigned char* constantColor); +void RB_CalcRGBFromDot(unsigned char* colors, float alphaMin, float alphaMax); +void RB_CalcRGBFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax); +void RB_CalcAlphaFromConstant(unsigned char* dstColors, int constantAlpha); +void RB_CalcAlphaFromDot(unsigned char* colors, float alphaMin, float alphaMax); +void RB_CalcAlphaFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax); +void RB_CalcAlphaFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st); +void RB_CalcRGBFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st); +void RB_CalcSpecularAlpha(unsigned char* alphas, float alphaMax, vec3_t lightOrigin); void RB_CalcLightGridColor(unsigned char* colors); void RB_CalcAlphaFromDotView(unsigned char* colors, float alphaMin, float alphaMax); void RB_CalcAlphaFromOneMinusDotView(unsigned char* colors, float alphaMin, float alphaMax); diff --git a/code/renderer/tr_shade.c b/code/renderer/tr_shade.c index b1c91af6..29cfb563 100644 --- a/code/renderer/tr_shade.c +++ b/code/renderer/tr_shade.c @@ -693,25 +693,37 @@ static void ComputeColors( shaderStage_t *pStage ) 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 ); + case CGEN_ENTITY: + RB_CalcColorFromEntity((unsigned char*)tess.svars.colors); + break; + case CGEN_ONE_MINUS_ENTITY: + RB_CalcColorFromOneMinusEntity((unsigned char*)tess.svars.colors); break; case CGEN_EXACT_VERTEX: + if (!tess.vertexColorValid) { + ri.Printf( + PRINT_WARNING, + "Vertex color specified for shader '%s', but vertex colors are not valid for this model\n", + tess.shader->name); + break; + } 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->colorConst; - } - break; case CGEN_VERTEX: - if ( tr.identityLight == 1 ) + if (!tess.vertexColorValid) { + ri.Printf( + PRINT_WARNING, + "Vertex color specified for shader '%s', but vertex colors are not valid for this model\n", + tess.shader->name); + break; + } + if (tr.identityLight == 1) { - Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); + Com_Memcpy(tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof(tess.vertexColors[0])); } else { - for ( i = 0; i < tess.numVertexes; i++ ) + 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; @@ -740,25 +752,56 @@ static void ComputeColors( shaderStage_t *pStage ) } } 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 ); + RB_CalcWaveColor(&pStage->rgbWave, (unsigned char*)tess.svars.colors, NULL); break; - case CGEN_ENTITY: - RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors ); + case CGEN_MULTIPLY_BY_WAVEFORM: + RB_CalcWaveColor(&pStage->rgbWave, (unsigned char*)tess.svars.colors, pStage->colorConst); break; - case CGEN_ONE_MINUS_ENTITY: - RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); + case CGEN_LIGHTING_GRID: + RB_CalcLightGridColor((unsigned int*)tess.svars.colors); + break; + case CGEN_LIGHTING_SPHERICAL: + case CGEN_STATIC: + if (!r_drawspherelights->integer) + break; + // FIXME: unimplemented + break; + case CGEN_CONSTANT: + RB_CalcColorFromConstant((unsigned char*)tess.svars.colors, pStage->colorConst); + break; + case CGEN_GLOBAL_COLOR: + RB_CalcColorFromConstant((unsigned char*)tess.svars.colors, backEnd.color2D); + break; + case CGEN_SCOORD: + RB_CalcRGBFromTexCoords( + (unsigned char*)tess.svars.colors, + pStage->alphaMin, + pStage->alphaMax, + pStage->alphaConstMin, + pStage->alphaConst, + 1.0, + 0.0, + tess.svars.texcoords[0][0] + ); + break; + case CGEN_TCOORD: + RB_CalcRGBFromTexCoords( + (unsigned char*)tess.svars.colors, + pStage->alphaMin, + pStage->alphaMax, + pStage->alphaConstMin, + pStage->alphaConst, + 0.0, + 1.0, + tess.svars.texcoords[0][0] + ); + break; + case CGEN_DOT: + RB_CalcRGBFromDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax); + break; + case CGEN_ONE_MINUS_DOT: + RB_CalcRGBFromOneMinusDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax); break; } @@ -779,38 +822,31 @@ static void ComputeColors( shaderStage_t *pStage ) } } break; - case AGEN_CONSTANT: - if ( pStage->rgbGen != CGEN_CONST ) { - for ( i = 0; i < tess.numVertexes; i++ ) { - tess.svars.colors[i][3] = pStage->colorConst[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 ); + RB_CalcAlphaFromEntity((unsigned char*)tess.svars.colors); break; case AGEN_ONE_MINUS_ENTITY: - RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); + RB_CalcAlphaFromOneMinusEntity((unsigned char*)tess.svars.colors); break; - case AGEN_VERTEX: - if ( pStage->rgbGen != CGEN_VERTEX ) { - for ( i = 0; i < tess.numVertexes; i++ ) { + 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++ ) - { + break; + case AGEN_ONE_MINUS_VERTEX: + for (i = 0; i < tess.numVertexes; i++) + { tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3]; - } - break; + } + break; + case AGEN_LIGHTING_SPECULAR: + RB_CalcSpecularAlpha((unsigned char*)tess.svars.colors, pStage->alphaMax, pStage->specOrigin); + break; + case AGEN_WAVEFORM: + RB_CalcWaveAlpha(&pStage->alphaWave, (unsigned char*)tess.svars.colors); + break; case AGEN_PORTAL: { unsigned char alpha; @@ -842,6 +878,62 @@ static void ComputeColors( shaderStage_t *pStage ) } } break; + case AGEN_DOT: + RB_CalcAlphaFromDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax); + return; + case AGEN_ONE_MINUS_DOT: + RB_CalcAlphaFromOneMinusDot((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax); + return; + case AGEN_CONSTANT: + RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, pStage->colorConst[3]); + break; + case AGEN_GLOBAL_ALPHA: + RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, backEnd.color2D[3]); + break; + case AGEN_SKYALPHA: + RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, tr.refdef.sky_alpha * 255.0); + break; + case AGEN_ONE_MINUS_SKYALPHA: + RB_CalcAlphaFromConstant((unsigned char*)tess.svars.colors, (1.0 - tr.refdef.sky_alpha) * 255.0); + break; + case AGEN_SCOORD: + RB_CalcAlphaFromTexCoords( + (unsigned char*)tess.svars.colors, + pStage->alphaMin, + pStage->alphaMax, + pStage->alphaConstMin, + pStage->alphaConst, + 1.0, + 0.0, + tess.svars.texcoords[0][0] + ); + break; + case AGEN_TCOORD: + RB_CalcAlphaFromTexCoords( + (unsigned char*)tess.svars.colors, + pStage->alphaMin, + pStage->alphaMax, + pStage->alphaConstMin, + pStage->alphaConst, + 0.0, + 1.0, + tess.svars.texcoords[0][0] + ); + break; + case AGEN_DIST_FADE: + // FIXME: unimplemented + break; + case AGEN_ONE_MINUS_DIST_FADE: + // FIXME: unimplemented + break; + case AGEN_DOT_VIEW: + RB_CalcAlphaFromDotView((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax); + break; + case AGEN_ONE_MINUS_DOT_VIEW: + RB_CalcAlphaFromOneMinusDotView((unsigned char*)tess.svars.colors, pStage->alphaMin, pStage->alphaMax); + break; + default: + break; } } diff --git a/code/renderer/tr_shade_calc.c b/code/renderer/tr_shade_calc.c index f0e907fa..3e474959 100644 --- a/code/renderer/tr_shade_calc.c +++ b/code/renderer/tr_shade_calc.c @@ -262,7 +262,7 @@ Change a polygon into a bunch of text polygons void DeformText( const char *text ) { int i; vec3_t origin, width, height; - int len; + size_t len; int ch; byte color[4]; float bottom, top; @@ -632,6 +632,60 @@ void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ) } } +/* +** RB_CalcColorFromConstant +*/ +void RB_CalcColorFromConstant(unsigned char* dstColors, unsigned char* constantColor) +{ + int i; + + for (i = 0; i < tess.numVertexes; i++) { + dstColors[i * 4] = constantColor[i * 4]; + dstColors[i * 4 + 1] = constantColor[i * 4 + 1]; + dstColors[i * 4 + 2] = constantColor[i * 4 + 2]; + dstColors[i * 4 + 3] = constantColor[i * 4 + 3]; + } +} + +void RB_CalcRGBFromDot(unsigned char* colors, float alphaMin, float alphaMax) +{ + // FIXME: unimplemented +} + +void RB_CalcRGBFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax) +{ + // FIXME: unimplemented +} + +void RB_CalcAlphaFromConstant(unsigned char* dstColors, int constantAlpha) +{ + int i; + + for (i = 0; i < tess.numVertexes; i++) { + dstColors[i * 4 + 3] = constantAlpha; + } +} + +void RB_CalcAlphaFromDot(unsigned char* colors, float alphaMin, float alphaMax) +{ + // FIXME: unimplemented +} + +void RB_CalcAlphaFromOneMinusDot(unsigned char* colors, float alphaMin, float alphaMax) +{ + // FIXME: unimplemented +} + +void RB_CalcAlphaFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st) +{ + // FIXME: unimplemented +} + +void RB_CalcRGBFromTexCoords(unsigned char* colors, float alphaMin, float alphaMax, int alphaMinCap, int alphaCap, float sWeight, float tWeight, float* st) +{ + // FIXME: unimplemented +} + /* ** RB_CalcAlphaFromEntity */ @@ -671,7 +725,7 @@ void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ) /* ** RB_CalcWaveColor */ -void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ) +void RB_CalcWaveColor(const waveForm_t* wf, unsigned char* dstColors, unsigned char* constantColor) { int i; int v; @@ -693,10 +747,20 @@ void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ) glow = 1; } - v = myftol( 255 * glow ); - color[0] = color[1] = color[2] = v; + if (constantColor) + { + color[0] = constantColor[0] * glow; + color[1] = constantColor[1] * glow; + color[2] = constantColor[2] * glow; + } + else + { + v = myftol(255 * glow); + color[0] = color[1] = color[2] = v; + } + color[3] = 255; - v = *(int *)color; + v = *(int*)color; for ( i = 0; i < tess.numVertexes; i++, colors++ ) { *colors = v; @@ -1034,7 +1098,7 @@ long myftol( float f ) { */ vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically -void RB_CalcSpecularAlpha( unsigned char *alphas ) { +void RB_CalcSpecularAlpha(unsigned char* alphas, float alphaMax, vec3_t lightOrigin) { int i; float *v, *normal; vec3_t viewer, reflected; diff --git a/code/renderer/tr_shader.c b/code/renderer/tr_shader.c index 336bf35b..21be81f7 100644 --- a/code/renderer/tr_shader.c +++ b/code/renderer/tr_shader.c @@ -853,7 +853,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) stage->colorConst[1] = 255 * color[1]; stage->colorConst[2] = 255 * color[2]; - stage->rgbGen = CGEN_CONST; + stage->rgbGen = CGEN_CONSTANT; } else if ( !Q_stricmp( token, "identity" ) ) { @@ -882,9 +882,13 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) { stage->rgbGen = CGEN_EXACT_VERTEX; } - else if ( !Q_stricmp( token, "lightingDiffuse" ) ) + else if ( !Q_stricmp( token, "lightingGrid" ) ) { - stage->rgbGen = CGEN_LIGHTING_DIFFUSE; + stage->rgbGen = CGEN_LIGHTING_GRID; + } + else if ( !Q_stricmp( token, "lightingSpherical" ) ) + { + stage->rgbGen = CGEN_LIGHTING_SPHERICAL; } else if ( !Q_stricmp( token, "oneMinusVertex" ) ) { @@ -1084,7 +1088,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) // decide which agens we can skip if ( stage->alphaGen == CGEN_IDENTITY ) { if ( stage->rgbGen == CGEN_IDENTITY - || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) { + || stage->rgbGen == CGEN_LIGHTING_GRID + || stage->rgbGen == CGEN_LIGHTING_SPHERICAL ) { stage->alphaGen = AGEN_SKIP; } } @@ -1695,11 +1700,11 @@ static void ComputeStageIteratorFunc( void ) // if ( shader.numUnfoggedPasses == 1 ) { - if ( unfoggedStages[0].rgbGen == CGEN_LIGHTING_DIFFUSE ) + if ( unfoggedStages[0].rgbGen == CGEN_LIGHTING_GRID || unfoggedStages[0].rgbGen == CGEN_LIGHTING_SPHERICAL ) { - if ( unfoggedStages[0].alphaGen == AGEN_IDENTITY ) + if ( unfoggedStages[0].alphaGen == AGEN_IDENTITY || unfoggedStages[0].alphaGen == AGEN_SKIP) { - if ( unfoggedStages[0].bundle[0].tcGen == TCGEN_TEXTURE ) + if ( unfoggedStages[0].bundle[0].tcGen == TCGEN_TEXTURE && unfoggedStages[0].bundle[1].tcGen == TCGEN_LIGHTMAP) { if ( !shader.polygonOffset ) { @@ -1722,7 +1727,7 @@ static void ComputeStageIteratorFunc( void ) // if ( shader.numUnfoggedPasses == 1 ) { - if ( ( unfoggedStages[0].rgbGen == CGEN_IDENTITY ) && ( unfoggedStages[0].alphaGen == AGEN_IDENTITY ) ) + if ( ( unfoggedStages[0].rgbGen == CGEN_IDENTITY ) && ( unfoggedStages[0].alphaGen == AGEN_IDENTITY || unfoggedStages[0].alphaGen == AGEN_SKIP ) ) { if ( unfoggedStages[0].bundle[0].tcGen == TCGEN_TEXTURE && unfoggedStages[0].bundle[1].tcGen == TCGEN_LIGHTMAP ) @@ -2120,7 +2125,7 @@ static void VertexLightingCollapse( void ) { unfoggedStages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); unfoggedStages[0].stateBits |= GLS_DEPTHMASK_TRUE; if ( shader.lightmapIndex == LIGHTMAP_NONE ) { - unfoggedStages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; + unfoggedStages[0].rgbGen = CGEN_LIGHTING_GRID; } else { unfoggedStages[0].rgbGen = CGEN_EXACT_VERTEX; } @@ -2203,10 +2208,6 @@ static shader_t *FinishShader( void ) { for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { shaderStage_t *pStage = &unfoggedStages[stage]; - if ( !pStage->active ) { - break; - } - // check for a missing texture if ( !pStage->bundle[0].image[0] ) { ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name ); @@ -2214,6 +2215,12 @@ static shader_t *FinishShader( void ) { continue; } + if (pStage->rgbGen == CGEN_LIGHTING_GRID) { + shader.needsLGrid = 1; + } else if (pStage->rgbGen == CGEN_LIGHTING_SPHERICAL || pStage->rgbGen == CGEN_STATIC) { + shader.needsLSpherical = 1; + } + // // default texture coordinate generation // @@ -2266,7 +2273,7 @@ static shader_t *FinishShader( void ) { // // if we are in r_vertexLight mode, never use a lightmap texture // - if ( stage > 1 && ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) { + if ( stage > 1 && r_vertexLight->integer ) { VertexLightingCollapse(); stage = 1; hasLightmapStage = qfalse; @@ -2275,28 +2282,31 @@ static shader_t *FinishShader( void ) { // // look for multitexture potential // - if ( stage > 1 && CollapseMultitexture() ) { - stage--; + if (stage > 1 && qglActiveTextureARB) { + CollapseMultitexture(); + }; + + // FIXME: fog shader + + // fogonly shaders don't have any normal passes + if (stage == 0) { + shader.sort = SS_OPAQUE; } - if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) { - if (vertexLightmap) { - ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name ); - } else { - ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name ); - shader.lightmapIndex = LIGHTMAP_NONE; - } + if (shader.lightmapIndex >= 0 && !hasLightmapStage) { + ri.Printf(PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name); + shader.lightmapIndex = LIGHTMAP_NONE; } - // // compute number of passes // - shader.numUnfoggedPasses = stage; - - // fogonly shaders don't have any normal passes - if ( stage == 0 ) { - shader.sort = SS_FOG; + shader.numUnfoggedPasses = 0; + for (stage = 0; stage < MAX_SHADER_STAGES; stage++) { + shaderStage_t* pStage = &unfoggedStages[stage]; + if (pStage->active) { + shader.numUnfoggedPasses++; + } } // determine which stage iterator function is appropriate