diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index b685d23b5a..cc2a3a0778 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -1573,6 +1573,7 @@ void GLShader_generic2D::SetShaderProgramUniforms( shaderProgram_t *shaderProgra GLShader_generic::GLShader_generic( GLShaderManager *manager ) : GLShader( "generic", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager ), + u_MapOverBrightBitsShift( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), u_ViewUp( this ), @@ -1610,6 +1611,7 @@ void GLShader_generic::SetShaderProgramUniforms( shaderProgram_t *shaderProgram GLShader_lightMapping::GLShader_lightMapping( GLShaderManager *manager ) : GLShader( "lightMapping", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT | ATTR_COLOR, manager ), + u_MapOverBrightBitsShift( this ), u_TextureMatrix( this ), u_SpecularExponent( this ), u_ColorModulate( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index 80c0fa21e4..a374fd9606 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -1304,6 +1304,21 @@ class GLCompileMacro_USE_ALPHA_TESTING : } }; +class u_MapOverBrightBitsShift : + GLUniform1i +{ +public: + u_MapOverBrightBitsShift( GLShader *shader ) : + GLUniform1i( shader, "u_MapOverBrightBitsShift" ) + { + } + + void SetUniform_MapOverBrightBitsShift( int mapOverBrightBitsShift ) + { + this->SetValue( mapOverBrightBitsShift ); + } +}; + class u_TextureMatrix : GLUniformMatrix4f { @@ -2238,6 +2253,7 @@ class GLShader_generic2D : class GLShader_generic : public GLShader, + public u_MapOverBrightBitsShift, public u_TextureMatrix, public u_ViewOrigin, public u_ViewUp, @@ -2267,6 +2283,7 @@ class GLShader_generic : class GLShader_lightMapping : public GLShader, + public u_MapOverBrightBitsShift, public u_TextureMatrix, public u_SpecularExponent, public u_ColorModulate, diff --git a/src/engine/renderer/glsl_source/generic_fp.glsl b/src/engine/renderer/glsl_source/generic_fp.glsl index f422a16f9a..18b61066b4 100644 --- a/src/engine/renderer/glsl_source/generic_fp.glsl +++ b/src/engine/renderer/glsl_source/generic_fp.glsl @@ -33,8 +33,26 @@ IN(smooth) vec2 var_FadeDepth; uniform sampler2D u_DepthMap; #endif +#if !defined(GENERIC_2D) && defined(USE_TCGEN_LIGHTMAP) +uniform int u_MapOverBrightBitsShift; +#endif + DECLARE_OUTPUT(vec4) +void mapOverBrightBits(inout vec3 color, in float shift) +{ + if (shift > 1) + { + color *= shift; + float maxComponent = 1.0; + maxComponent = max(maxComponent, color.r); + maxComponent = max(maxComponent, color.g); + maxComponent = max(maxComponent, color.b); + maxComponent = 1.0 / maxComponent; + color *= maxComponent; + } +} + void main() { vec4 color = texture2D(u_ColorMap, var_TexCoords); @@ -53,7 +71,12 @@ void main() color.a *= smoothstep(gl_FragCoord.z, fadeDepth, depth); #endif +#if !defined(GENERIC_2D) && defined(USE_TCGEN_LIGHTMAP) + mapOverBrightBits(color.rgb, u_MapOverBrightBitsShift); +#endif + color *= var_Color; + outputColor = color; #if defined(GENERIC_2D) diff --git a/src/engine/renderer/glsl_source/lightMapping_fp.glsl b/src/engine/renderer/glsl_source/lightMapping_fp.glsl index ef1d1b7bb9..be6544c1cf 100644 --- a/src/engine/renderer/glsl_source/lightMapping_fp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_fp.glsl @@ -59,8 +59,24 @@ IN(smooth) vec3 var_Normal; uniform vec3 u_LightGridScale; #endif +uniform int u_MapOverBrightBitsShift; + DECLARE_OUTPUT(vec4) +void mapOverBrightBits(inout vec3 color, in float shift) +{ + if (shift > 1) + { + color *= shift; + float maxComponent = 1.0; + maxComponent = max(maxComponent, color.r); + maxComponent = max(maxComponent, color.g); + maxComponent = max(maxComponent, color.b); + maxComponent = 1.0 / maxComponent; + color *= maxComponent; + } +} + void main() { // Compute view direction in world space. @@ -124,6 +140,8 @@ void main() vec3 ambientColor, lightColor; ReadLightGrid(texture3D(u_LightGrid1, lightGridPos), ambientColor, lightColor); + mapOverBrightBits(ambientColor.rgb, u_MapOverBrightBitsShift); + color.rgb = ambientColor * r_AmbientScale * diffuse.rgb; #endif @@ -153,6 +171,8 @@ void main() lightColor /= clamp(dot(normalize(var_Normal), lightDir), 0.3, 1.0); #endif + mapOverBrightBits(lightColor.rgb, u_MapOverBrightBitsShift); + // Blend static light. #if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) computeDeluxeLight(lightDir, normal, viewDir, lightColor, diffuse, material, color); diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index 6a361c461b..14c4b1a76b 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -46,118 +46,6 @@ static int c_vboShadowSurfaces; //=============================================================================== -/* -=============== -R_ColorShiftLightingBytes -=============== -*/ -static void R_ColorShiftLightingBytes( byte in[ 4 ], byte out[ 4 ] ) -{ - int shift, r, g, b; - - /* Shift the color data based on overbright range. - - Historically the shift was: - - shift = tr.mapOverBrightBits - tr.overbrightBits; - - But in Dæmon engine tr.overbrightBits is always zero - as this value is zero when there hardware overbright - bit is disabled, and the engine doesn't implement - hardware overbright bit at all. - - The original code was there to only shift in software - what hardware overbright bit feature was not doing, but - this implementation is entirely software. */ - shift = tr.mapOverBrightBits; - - // shift the data based on overbright range - r = in[ 0 ] << shift; - g = in[ 1 ] << shift; - b = in[ 2 ] << shift; - - // normalize by color instead of saturating to white - if ( ( r | g | b ) > 255 ) - { - int max; - - max = r > g ? r : g; - max = max > b ? max : b; - r = r * 255 / max; - g = g * 255 / max; - b = b * 255 / max; - } - - out[ 0 ] = r; - out[ 1 ] = g; - out[ 2 ] = b; - out[ 3 ] = in[ 3 ]; -} - -static void R_ColorShiftLightingBytesCompressed( byte in[ 8 ], byte out[ 8 ] ) -{ - unsigned short rgb565; - byte rgba[4]; - - // color shift the endpoint colors in the dxt block - rgb565 = in[1] << 8 | in[0]; - rgba[0] = (rgb565 >> 8) & 0xf8; - rgba[1] = (rgb565 >> 3) & 0xfc; - rgba[2] = (rgb565 << 3) & 0xf8; - rgba[3] = 0xff; - R_ColorShiftLightingBytes( rgba, rgba ); - rgb565 = ((rgba[0] >> 3) << 11) | - ((rgba[1] >> 2) << 5) | - ((rgba[2] >> 3) << 0); - out[0] = rgb565 & 0xff; - out[1] = rgb565 >> 8; - - rgb565 = in[3] << 8 | in[2]; - rgba[0] = (rgb565 >> 8) & 0xf8; - rgba[1] = (rgb565 >> 3) & 0xfc; - rgba[2] = (rgb565 << 3) & 0xf8; - rgba[3] = 0xff; - R_ColorShiftLightingBytes( rgba, rgba ); - rgb565 = ((rgba[0] >> 3) << 11) | - ((rgba[1] >> 2) << 5) | - ((rgba[2] >> 3) << 0); - out[2] = rgb565 & 0xff; - out[3] = rgb565 >> 8; -} - -/* -=============== -R_ProcessLightmap - - returns maxIntensity -=============== -*/ -float R_ProcessLightmap( byte *pic, int in_padding, int width, int height, int bits, byte *pic_out ) -{ - int j; - float maxIntensity = 0; - - if( bits & IF_BC1 ) { - for ( j = 0; j < ((width + 3) >> 2) * ((height + 3) >> 2); j++ ) - { - R_ColorShiftLightingBytesCompressed( &pic[ j * 8 ], &pic_out[ j * 8 ] ); - } - } else if( bits & (IF_BC2 | IF_BC3) ) { - for ( j = 0; j < ((width + 3) >> 2) * ((height + 3) >> 2); j++ ) - { - R_ColorShiftLightingBytesCompressed( &pic[ j * 16 ], &pic_out[ j * 16 ] ); - } - } else { - for ( j = 0; j < width * height; j++ ) - { - R_ColorShiftLightingBytes( &pic[ j * in_padding ], &pic_out[ j * 4 ] ); - pic_out[ j * 4 + 3 ] = 255; - } - } - - return maxIntensity; -} - static int LightmapNameCompare( const char *s1, const char *s2 ) { int c1, c2; @@ -640,7 +528,7 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName ) lightMapBuffer[( index * 4 ) + 2 ] = buf_p[( ( x + ( y * internalLightMapSize ) ) * 3 ) + 2 ]; lightMapBuffer[( index * 4 ) + 3 ] = 255; - R_ColorShiftLightingBytes( &lightMapBuffer[( index * 4 ) + 0 ], &lightMapBuffer[( index * 4 ) + 0 ] ); + // Color shift for overbright bits is now done in GLSL. } } @@ -925,7 +813,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf, in cv->verts[ i ].lightColor = Color::Adapt( verts[ i ].color ); - R_ColorShiftLightingBytes( cv->verts[ i ].lightColor.ToArray(), cv->verts[ i ].lightColor.ToArray() ); + // Color shift for overbright bits is now done in GLSL. } // copy triangles @@ -1132,7 +1020,7 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf ) points[ i ].lightColor = Color::Adapt( verts[ i ].color ); - R_ColorShiftLightingBytes( points[ i ].lightColor.ToArray(), points[ i ].lightColor.ToArray() ); + // Color shift for overbright bits is now done in GLSL. } // center texture coords @@ -1256,7 +1144,7 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf, cv->verts[ i ].lightColor = Color::Adapt( verts[ i ].color ); - R_ColorShiftLightingBytes( cv->verts[ i ].lightColor.ToArray(), cv->verts[ i ].lightColor.ToArray() ); + // Color shift for overbright bits is now done in GLSL. } // copy triangles @@ -4044,8 +3932,7 @@ void R_LoadLightGrid( lump_t *l ) tmpDirected[ 2 ] = in->directed[ 2 ]; tmpDirected[ 3 ] = 255; - R_ColorShiftLightingBytes( tmpAmbient, tmpAmbient ); - R_ColorShiftLightingBytes( tmpDirected, tmpDirected ); + // Color shift for overbright bits is now done in GLSL. for ( j = 0; j < 3; j++ ) { @@ -6922,4 +6809,6 @@ void RE_LoadWorldMap( const char *name ) } } } + + tr.mapOverBrightBitsShift = pow(2, tr.mapOverBrightBits); } diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index c5ae2f1546..e5ab3b4455 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1798,10 +1798,7 @@ image_t *R_FindImageFile( const char *imageName, imageParams_t &imageParams ) return nullptr; } - if ( imageParams.bits & IF_LIGHTMAP ) - { - R_ProcessLightmap( pic[ 0 ], 4, width, height, imageParams.bits, pic[ 0 ] ); - } + // Color shift for overbright bits is now done in GLSL. image = R_CreateImage( ( char * ) buffer, (const byte **)pic, width, height, numMips, imageParams ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 97719b56bb..1b41d33531 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2822,7 +2822,8 @@ enum class deluxeMode_t { NONE, GRID, MAP }; viewParms_t viewParms; - int mapOverBrightBits; // r_mapOverbrightBits->integer, but can be overridden by mapper using the worldspawn + int mapOverBrightBits; // r_mapOverbrightBits->integer, but can be overridden by mapper using the worldspawn + int mapOverBrightBitsShift; // pow(2, mapOverbrightBits) orientationr_t orientation; // for current entity @@ -3305,7 +3306,6 @@ inline bool checkGLErrors() void RE_Shutdown( bool destroyWindow ); bool R_GetEntityToken( char *buffer, int size ); - float R_ProcessLightmap( byte *pic, int in_padding, int width, int height, int bits, byte *pic_out ); // Arnout model_t *R_AllocModel(); diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 9ab73acbcb..f94f10501b 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -732,6 +732,12 @@ static void Render_generic( shaderStage_t *pStage ) gl_genericShader->SetUniform_AlphaTest(pStage->stateBits); } + // u_MapOverBrightBitsShift + if ( pStage->tcGen_Lightmap ) + { + gl_genericShader->SetUniform_MapOverBrightBitsShift( tr.mapOverBrightBitsShift ); + } + // u_ColorGen switch ( pStage->rgbGen ) { @@ -895,6 +901,7 @@ static void Render_lightMapping( shaderStage_t *pStage ) lightMode_t lightMode = lightMode_t::FULLBRIGHT; deluxeMode_t deluxeMode = deluxeMode_t::NONE; + int mapOverBrightBitsShift = 1; /* TODO: investigate what this is. It's probably a hack to detect some specific use case. Without knowing which use case this takes care about, @@ -949,6 +956,7 @@ static void Render_lightMapping( shaderStage_t *pStage ) switch ( lightMode ) { case lightMode_t::VERTEX: + mapOverBrightBitsShift = tr.mapOverBrightBitsShift; // Do not rewrite pStage->rgbGen. colorGen = colorGen_t::CGEN_VERTEX; tess.svars.color.SetRed( 0.0f ); @@ -957,12 +965,14 @@ static void Render_lightMapping( shaderStage_t *pStage ) break; case lightMode_t::GRID: + mapOverBrightBitsShift = tr.mapOverBrightBitsShift; // Store lightGrid1 as lightmap, // the GLSL code will know how to deal with it. lightmap = tr.lightGrid1Image; break; case lightMode_t::MAP: + mapOverBrightBitsShift = tr.mapOverBrightBitsShift; lightmap = GetLightMap(); if ( r_showLightMaps->integer ) @@ -1085,6 +1095,9 @@ static void Render_lightMapping( shaderStage_t *pStage ) // u_AlphaTest gl_lightMappingShader->SetUniform_AlphaTest( pStage->stateBits ); + // u_MapOverBrightBitsShift + gl_lightMappingShader->SetUniform_MapOverBrightBitsShift( mapOverBrightBitsShift ); + // bind u_HeightMap if ( pStage->enableReliefMapping ) { diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index 077526f123..098d646e84 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -1450,6 +1450,9 @@ static bool LoadMap( shaderStage_t *stage, const char *buffer, const int bundleI else if ( !Q_stricmp( token, "$lightmap" ) ) { stage->type = stageType_t::ST_LIGHTMAP; + /* This is not needed to compute coordinates, but we use this to select + specific lightmap code in generic_fp.glsl. */ + stage->tcGen_Lightmap = true; return true; }