Skip to content

Commit f27fdce

Browse files
committed
Implement partial overbright clamping like q3
The lighting values continue to be multiplied by pow(2, tr.mapOverbrightBits) but the resulting values are capped at pow(2, tr.overbrightBits) which defaults to 1. This matches the original behavior of Quake 3 (in full screen mode) and Tremulous 1.1.0. The cvar r_overbrightBits has come back and has the same behavior as ioq3. Setting r_overbrightBits to 0 gives you the behavior of pre-0.55 Unvanquished. Setting r_overbrightBits to 2 gives you 0.55.x behavior. See #1542 for more information.
1 parent ed598c3 commit f27fdce

File tree

4 files changed

+27
-45
lines changed

4 files changed

+27
-45
lines changed

src/engine/renderer/tr_bsp.cpp

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,7 @@ static void R_ColorShiftLightingBytes( byte bytes[ 4 ] )
7474
backward compatible with this bug for diagnostic purpose and fair comparison with
7575
other buggy engines. */
7676

77-
if ( tr.mapOverBrightBits == 0 )
78-
{
79-
return;
80-
}
77+
ASSERT_LT( tr.overbrightBits, tr.mapOverBrightBits );
8178

8279
/* Shift the color data based on overbright range.
8380
@@ -94,7 +91,7 @@ static void R_ColorShiftLightingBytes( byte bytes[ 4 ] )
9491
what hardware overbright bit feature was not doing, but
9592
this implementation is entirely software. */
9693

97-
int shift = tr.mapOverBrightBits;
94+
int shift = tr.mapOverBrightBits - tr.overbrightBits;
9895

9996
// shift the data based on overbright range
10097
int r = bytes[ 0 ] << shift;
@@ -120,10 +117,7 @@ static void R_ColorShiftLightingBytes( byte bytes[ 4 ] )
120117

121118
static void R_ColorShiftLightingBytesCompressed( byte bytes[ 8 ] )
122119
{
123-
if ( tr.mapOverBrightBits == 0 )
124-
{
125-
return;
126-
}
120+
ASSERT_LT( tr.overbrightBits, tr.mapOverBrightBits );
127121

128122
// color shift the endpoint colors in the dxt block
129123
unsigned short rgb565 = bytes[1] << 8 | bytes[0];
@@ -164,7 +158,7 @@ R_ProcessLightmap
164158
*/
165159
void R_ProcessLightmap( byte *bytes, int width, int height, int bits )
166160
{
167-
if ( tr.mapOverBrightBits == 0 )
161+
if ( tr.overbrightBits >= tr.mapOverBrightBits )
168162
{
169163
return;
170164
}
@@ -668,7 +662,7 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
668662
lightMapBuffer[( index * 4 ) + 2 ] = buf_p[( ( x + ( y * internalLightMapSize ) ) * 3 ) + 2 ];
669663
lightMapBuffer[( index * 4 ) + 3 ] = 255;
670664

671-
if ( tr.legacyOverBrightClamping )
665+
if ( tr.overbrightBits < tr.mapOverBrightBits )
672666
{
673667
R_ColorShiftLightingBytes( &lightMapBuffer[( index * 4 ) + 0 ] );
674668
}
@@ -1029,7 +1023,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf, in
10291023
cv->verts[ i ].lightColor = Color::Adapt( verts[ i ].color );
10301024

10311025

1032-
if ( tr.legacyOverBrightClamping )
1026+
if ( tr.overbrightBits < tr.mapOverBrightBits )
10331027
{
10341028
R_ColorShiftLightingBytes( cv->verts[ i ].lightColor.ToArray() );
10351029
}
@@ -1239,7 +1233,7 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf )
12391233

12401234
points[ i ].lightColor = Color::Adapt( verts[ i ].color );
12411235

1242-
if ( tr.legacyOverBrightClamping )
1236+
if ( tr.overbrightBits < tr.mapOverBrightBits )
12431237
{
12441238
R_ColorShiftLightingBytes( points[ i ].lightColor.ToArray() );
12451239
}
@@ -1366,7 +1360,7 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf,
13661360

13671361
cv->verts[ i ].lightColor = Color::Adapt( verts[ i ].color );
13681362

1369-
if ( tr.legacyOverBrightClamping )
1363+
if ( tr.overbrightBits < tr.mapOverBrightBits )
13701364
{
13711365
R_ColorShiftLightingBytes( cv->verts[ i ].lightColor.ToArray() );
13721366
}
@@ -4112,7 +4106,7 @@ void R_LoadLightGrid( lump_t *l )
41124106
tmpDirected[ 2 ] = in->directed[ 2 ];
41134107
tmpDirected[ 3 ] = 255;
41144108

4115-
if ( tr.legacyOverBrightClamping )
4109+
if ( tr.overbrightBits < tr.mapOverBrightBits )
41164110
{
41174111
R_ColorShiftLightingBytes( tmpAmbient );
41184112
R_ColorShiftLightingBytes( tmpDirected );
@@ -4372,24 +4366,6 @@ void R_LoadEntities( lump_t *l, std::string &externalEntities )
43724366
tr.mapOverBrightBits = Math::Clamp( atof( value ), 0.0, 3.0 );
43734367
continue;
43744368
}
4375-
4376-
if ( !Q_stricmp( keyname, "overbrightClamping" ) )
4377-
{
4378-
if ( !Q_stricmp( value, "0" ) )
4379-
{
4380-
tr.legacyOverBrightClamping = false;
4381-
}
4382-
else if ( !Q_stricmp( value, "1" ) )
4383-
{
4384-
tr.legacyOverBrightClamping = true;
4385-
}
4386-
else
4387-
{
4388-
Log::Warn( "invalid value for worldspawn key overbrightClamping" );
4389-
}
4390-
4391-
continue;
4392-
}
43934369
}
43944370

43954371
// check for deluxe mapping provided by NetRadiant's q3map2
@@ -5122,6 +5098,9 @@ void RE_LoadWorldMap( const char *name )
51225098
}
51235099
R_LoadEntities( &header->lumps[ LUMP_ENTITIES ], externalEntities );
51245100

5101+
// Now we can set this after checking a possible worldspawn value for mapOverbrightBits
5102+
tr.overbrightBits = std::min( tr.mapOverBrightBits, r_overbrightBits.Get() );
5103+
51255104
R_LoadShaders( &header->lumps[ LUMP_SHADERS ] );
51265105

51275106
R_LoadLightmaps( &header->lumps[ LUMP_LIGHTMAPS ], name );
@@ -5159,7 +5138,6 @@ void RE_LoadWorldMap( const char *name )
51595138
tr.worldLight = tr.lightMode;
51605139
tr.modelLight = lightMode_t::FULLBRIGHT;
51615140
tr.modelDeluxe = deluxeMode_t::NONE;
5162-
tr.mapLightFactor = 1.0f;
51635141

51645142
// Use fullbright lighting for everything if the world is fullbright.
51655143
if ( tr.worldLight != lightMode_t::FULLBRIGHT )
@@ -5233,9 +5211,9 @@ void RE_LoadWorldMap( const char *name )
52335211

52345212
/* Set GLSL overbright parameters if the legacy clamped overbright isn't used
52355213
and the lighting mode is not fullbright. */
5236-
if ( !tr.legacyOverBrightClamping && tr.lightMode != lightMode_t::FULLBRIGHT )
5214+
if ( tr.lightMode != lightMode_t::FULLBRIGHT )
52375215
{
5238-
tr.mapLightFactor = pow( 2, tr.mapOverBrightBits );
5216+
tr.mapLightFactor = float( 1 << tr.overbrightBits );
52395217
}
52405218

52415219
tr.worldLoaded = true;

src/engine/renderer/tr_image.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,7 +1853,7 @@ image_t *R_FindImageFile( const char *imageName, imageParams_t &imageParams )
18531853
return nullptr;
18541854
}
18551855

1856-
if ( imageParams.bits & IF_LIGHTMAP && tr.legacyOverBrightClamping )
1856+
if ( imageParams.bits & IF_LIGHTMAP )
18571857
{
18581858
R_ProcessLightmap( *pic, width, height, imageParams.bits );
18591859
}
@@ -3054,6 +3054,7 @@ void R_InitImages()
30543054
tr.lightmaps.reserve( 128 );
30553055
tr.deluxemaps.reserve( 128 );
30563056

3057+
//TODO rewrite WoT with new info :)
30573058
/* These are the values expected by the rest of the renderer
30583059
(esp. tr_bsp), used for "gamma correction of the map".
30593060
Both were set to 0 if we had neither COMPAT_ET nor COMPAT_Q3,
@@ -3113,8 +3114,9 @@ void R_InitImages()
31133114
Because tr.overbrightBits is always 0, tr.identityLight is
31143115
always 1.0f. We can entirely remove it. */
31153116

3117+
// TODO is there any reason to set these before a map is loaded?
31163118
tr.mapOverBrightBits = r_overbrightDefaultExponent.Get();
3117-
tr.legacyOverBrightClamping = r_overbrightDefaultClamp.Get();
3119+
tr.overbrightBits = std::min(tr.mapOverBrightBits, r_overbrightBits.Get());
31183120

31193121
// create default texture and white texture
31203122
R_CreateBuiltinImages();

src/engine/renderer/tr_init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9292
cvar_t *r_realtimeLightingCastShadows;
9393
cvar_t *r_precomputedLighting;
9494
Cvar::Cvar<int> r_overbrightDefaultExponent("r_overbrightDefaultExponent", "default map light color shift (multiply by 2^x)", Cvar::NONE, 2);
95-
Cvar::Cvar<bool> r_overbrightDefaultClamp("r_overbrightDefaultClamp", "clamp lightmap colors to 1 (in absence of map worldspawn value)", Cvar::NONE, false);
95+
Cvar::Range<Cvar::Cvar<int>> r_overbrightBits("r_overbrightBits", "clamp lightmap colors to 2^x", Cvar::NONE, 1, 0, 3);
9696
Cvar::Cvar<bool> r_overbrightIgnoreMapSettings("r_overbrightIgnoreMapSettings", "force usage of r_overbrightDefaultClamp / r_overbrightDefaultExponent, ignoring worldspawn", Cvar::NONE, false);
9797
Cvar::Range<Cvar::Cvar<int>> r_lightMode("r_lightMode", "lighting mode: 0: fullbright (cheat), 1: vertex light, 2: grid light (cheat), 3: light map", Cvar::NONE, Util::ordinal(lightMode_t::MAP), Util::ordinal(lightMode_t::FULLBRIGHT), Util::ordinal(lightMode_t::MAP));
9898
Cvar::Cvar<bool> r_colorGrading( "r_colorGrading", "Use color grading", Cvar::NONE, true );
@@ -1185,7 +1185,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p
11851185
r_realtimeLightingCastShadows = Cvar_Get( "r_realtimeLightingCastShadows", "1", 0 );
11861186
r_precomputedLighting = Cvar_Get( "r_precomputedLighting", "1", CVAR_CHEAT | CVAR_LATCH );
11871187
Cvar::Latch( r_overbrightDefaultExponent );
1188-
Cvar::Latch( r_overbrightDefaultClamp );
1188+
Cvar::Latch( r_overbrightBits );
11891189
Cvar::Latch( r_overbrightIgnoreMapSettings );
11901190
Cvar::Latch( r_lightMode );
11911191
Cvar::Latch( r_colorGrading );

src/engine/renderer/tr_local.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,12 +2809,14 @@ enum class shaderProfilerRenderSubGroupsMode {
28092809

28102810
viewParms_t viewParms;
28112811

2812-
// r_overbrightDefaultExponent, but can be overridden by mapper using the worldspawn
2812+
// Brightness scaling: roughly speaking, a lightmap value of x will be interpreted as
2813+
// min(x * pow(2, mapOverBrightBits), pow(2, overbrightBits))
2814+
// (but when a component hits the max allowed value, others are scaled down to keep the "same color")
28132815
int mapOverBrightBits;
2814-
// pow(2, mapOverbrightBits)
2816+
// min(r_overbrightBits.Get(), mapOverBrightBits)
2817+
int overbrightBits;
2818+
// pow(2, overbrightBits)
28152819
float mapLightFactor;
2816-
// May have to be true on some legacy maps: clamp and normalize multiplied colors.
2817-
bool legacyOverBrightClamping;
28182820

28192821
orientationr_t orientation; // for current entity
28202822

@@ -2938,7 +2940,7 @@ enum class shaderProfilerRenderSubGroupsMode {
29382940
extern cvar_t *r_realtimeLightingCastShadows;
29392941
extern cvar_t *r_precomputedLighting;
29402942
extern Cvar::Cvar<int> r_overbrightDefaultExponent;
2941-
extern Cvar::Cvar<bool> r_overbrightDefaultClamp;
2943+
extern Cvar::Range<Cvar::Cvar<int>> r_overbrightBits;
29422944
extern Cvar::Cvar<bool> r_overbrightIgnoreMapSettings;
29432945
extern Cvar::Range<Cvar::Cvar<int>> r_lightMode;
29442946
extern Cvar::Cvar<bool> r_colorGrading;

0 commit comments

Comments
 (0)