OpenGL2: Fix q3map2 lightstyles effects

Fixes World of Padman wop_trashmap.

For r_mergeLightmaps 1
- Fix tcMod transform on "map $lightmap" stages
- Fix external lightmap image texcoords if shader also has an internal
  lightmap

For r_sunlightMode 1
- Fix "tcGen lightmap" stages with blendFunc GL_SRC_ALPHA GL_ONE being
  converted to white image + modulate lightmap and drawing incorrectly
This commit is contained in:
Zack Middleton 2023-12-20 23:12:56 -06:00
parent 972635ea5a
commit ae0878ca61
2 changed files with 99 additions and 9 deletions

View file

@ -497,6 +497,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
} }
// If FatPackU() or FatPackV() changes, update FixFatLightmapTexCoords()
static float FatPackU(float input, int lightmapnum) static float FatPackU(float input, int lightmapnum)
{ {
if (lightmapnum < 0) if (lightmapnum < 0)

View file

@ -2580,13 +2580,15 @@ static int CollapseStagesToGLSL(void)
numStages++; numStages++;
} }
// convert any remaining lightmap stages to a lighting pass with a white texture // convert any remaining lightmap stages with no blending or blendfunc filter
// to a lighting pass with a white texture
// only do this with r_sunlightMode non-zero, as it's only for correct shadows. // only do this with r_sunlightMode non-zero, as it's only for correct shadows.
if (r_sunlightMode->integer && shader.numDeforms == 0) if (r_sunlightMode->integer && shader.numDeforms == 0)
{ {
for (i = 0; i < MAX_SHADER_STAGES; i++) for (i = 0; i < MAX_SHADER_STAGES; i++)
{ {
shaderStage_t *pStage = &stages[i]; shaderStage_t *pStage = &stages[i];
int blendBits;
if (!pStage->active) if (!pStage->active)
continue; continue;
@ -2594,15 +2596,23 @@ static int CollapseStagesToGLSL(void)
if (pStage->adjustColorsForFog) if (pStage->adjustColorsForFog)
continue; continue;
if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP) if (pStage->bundle[TB_DIFFUSEMAP].tcGen != TCGEN_LIGHTMAP)
{ continue;
pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP; blendBits = pStage->stateBits & (GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS);
pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP];
pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage; if (blendBits != 0 &&
pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse; blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) &&
pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE; blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)) {
continue;
} }
pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP;
pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP];
pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage;
pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse;
pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE;
} }
} }
@ -2890,6 +2900,83 @@ static void VertexLightingCollapse( void ) {
} }
} }
/*
=================
FixFatLightmapTexCoords
Handle edge cases of altering lightmap texcoords for fat lightmap atlas
=================
*/
static void FixFatLightmapTexCoords(void)
{
texModInfo_t *tmi;
int lightmapnum;
int stage;
int size;
int i;
if ( !r_mergeLightmaps->integer || tr.fatLightmapCols <= 0) {
return;
}
if ( shader.lightmapIndex < 0 ) {
// no internal lightmap, texcoords were not modified
return;
}
lightmapnum = shader.lightmapIndex;
if (tr.worldDeluxeMapping)
lightmapnum >>= 1;
lightmapnum %= (tr.fatLightmapCols * tr.fatLightmapRows);
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
shaderStage_t *pStage = &stages[stage];
if ( !pStage->active ) {
break;
}
// fix tcMod transform for internal lightmaps, it may be used by q3map2 lightstyles
if ( pStage->bundle[0].isLightmap ) {
for ( i = 0; i < pStage->bundle[0].numTexMods; i++ ) {
tmi = &pStage->bundle[0].texMods[i];
if ( tmi->type == TMOD_TRANSFORM ) {
tmi->translate[0] /= (float)tr.fatLightmapCols;
tmi->translate[1] /= (float)tr.fatLightmapRows;
}
}
}
// add a tcMod transform for external lightmaps to convert back to the original texcoords
else if ( pStage->bundle[0].tcGen == TCGEN_LIGHTMAP ) {
if ( pStage->bundle[0].numTexMods == TR_MAX_TEXMODS ) {
ri.Printf( PRINT_DEVELOPER, "WARNING: too many tcmods to fix external lightmap texcoords for r_mergeLightmaps in shader '%s'", shader.name );
} else {
size = pStage->bundle[0].numTexMods * sizeof( texModInfo_t );
if ( size ) {
memmove( &pStage->bundle[0].texMods[1], &pStage->bundle[0].texMods[0], size );
}
tmi = &pStage->bundle[0].texMods[0];
pStage->bundle[0].numTexMods++;
tmi->matrix[0][0] = tr.fatLightmapCols;
tmi->matrix[0][1] = 0;
tmi->matrix[1][0] = 0;
tmi->matrix[1][1] = tr.fatLightmapRows;
tmi->translate[0] = -(lightmapnum % tr.fatLightmapCols);
tmi->translate[1] = -(lightmapnum / tr.fatLightmapCols);
tmi->type = TMOD_TRANSFORM;
}
}
}
}
/* /*
=============== ===============
InitShader InitShader
@ -3081,6 +3168,8 @@ static shader_t *FinishShader( void ) {
hasLightmapStage = qfalse; hasLightmapStage = qfalse;
} }
FixFatLightmapTexCoords();
// //
// look for multitexture potential // look for multitexture potential
// //