diff --git a/engine/Makefile b/engine/Makefile index 36a907dd..2dfea9ab 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -48,7 +48,7 @@ ifndef BUILD_AUTOUPDATER # DON'T build unless you mean to! endif # ioquake3 git commit that this is based on -IOQ3_REVISION = 972635ea +IOQ3_REVISION = 5ede35d8 ############################################################################# # diff --git a/engine/code/renderergl2/tr_bsp.c b/engine/code/renderergl2/tr_bsp.c index ad5fe3a3..b316351e 100644 --- a/engine/code/renderergl2/tr_bsp.c +++ b/engine/code/renderergl2/tr_bsp.c @@ -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) { if (lightmapnum < 0) diff --git a/engine/code/renderergl2/tr_shader.c b/engine/code/renderergl2/tr_shader.c index 0cd78a78..4b9fa991 100644 --- a/engine/code/renderergl2/tr_shader.c +++ b/engine/code/renderergl2/tr_shader.c @@ -1841,12 +1841,17 @@ static qboolean ParseShader( char **text ) tr.sunShadowScale = atof(token); // parse twice, since older shaders may include mapLightScale before sunShadowScale - token = COM_ParseExt( text, qfalse ); - if (token[0]) - tr.sunShadowScale = atof(token); + if (token[0]) { + token = COM_ParseExt( text, qfalse ); + if (token[0]) { + tr.sunShadowScale = atof(token); + } + } } - SkipRestOfLine( text ); + if (token[0]) { + SkipRestOfLine( text ); + } continue; } // tonemap parms @@ -2580,13 +2585,15 @@ static int CollapseStagesToGLSL(void) 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. if (r_sunlightMode->integer && shader.numDeforms == 0) { for (i = 0; i < MAX_SHADER_STAGES; i++) { shaderStage_t *pStage = &stages[i]; + int blendBits; if (!pStage->active) continue; @@ -2594,15 +2601,23 @@ static int CollapseStagesToGLSL(void) if (pStage->adjustColorsForFog) continue; - if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP) - { - 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; + if (pStage->bundle[TB_DIFFUSEMAP].tcGen != TCGEN_LIGHTMAP) + continue; + + blendBits = pStage->stateBits & (GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS); + + if (blendBits != 0 && + blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) && + 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 +2905,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 @@ -3081,6 +3173,8 @@ static shader_t *FinishShader( void ) { hasLightmapStage = qfalse; } + FixFatLightmapTexCoords(); + // // look for multitexture potential // diff --git a/engine/code/tools/lcc/cpp/lex.c b/engine/code/tools/lcc/cpp/lex.c index 8030354e..66092e1b 100644 --- a/engine/code/tools/lcc/cpp/lex.c +++ b/engine/code/tools/lcc/cpp/lex.c @@ -511,6 +511,25 @@ foldline(Source *s) return 0; } +// This doesn't have proper tracking across read() to only remove \r from \r\n sequence. +// The lexer doesn't correctly handle standalone \r anyway though. +int +crlf_to_lf(unsigned char *buf, int n) { + int i, count; + + count = 0; + + for (i = 0; i < n; i++) { + if (buf[i] == '\r') { + continue; + } + + buf[count++] = buf[i]; + } + + return count; +} + int fillbuf(Source *s) { @@ -521,6 +540,7 @@ fillbuf(Source *s) error(FATAL, "Input buffer overflow"); if (s->fd<0 || (n=read(s->fd, (char *)s->inl, INS/8)) <= 0) n = 0; + n = crlf_to_lf(s->inl, n); if ((*s->inp&0xff) == EOB) /* sentinel character appears in input */ *s->inp = EOFC; s->inl += n; diff --git a/engine/code/tools/lcc/cpp/unix.c b/engine/code/tools/lcc/cpp/unix.c index bac841d8..56f1fff5 100644 --- a/engine/code/tools/lcc/cpp/unix.c +++ b/engine/code/tools/lcc/cpp/unix.c @@ -65,6 +65,9 @@ setup(int argc, char **argv) fp = (char*)newstring((uchar*)argv[optind], strlen(argv[optind]), 0); if ((fd = open(fp, 0)) <= 0) error(FATAL, "Can't open input file %s", fp); +#ifdef WIN32 + _setmode(fd, _O_BINARY); +#endif } if (optind+1