mirror of
https://github.com/FWGS/xash3d-fwgs
synced 2024-11-29 21:50:08 +01:00
Alibek Omarov
df6546d5b1
* immediately expose it in RefAPI. Bump RefAPI to version 7. * remove VID_StartupGamma, it's not used anymore * remove stub lightgamma and direct cvars * add a temporary check for v_direct and v_lightgamma default values
215 lines
5.5 KiB
C
215 lines
5.5 KiB
C
/*
|
|
gamma.c - gamma routines
|
|
Copyright (C) 2011 Uncle Mike
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "client.h"
|
|
#include "xash3d_mathlib.h"
|
|
#include "enginefeatures.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gamma conversion support
|
|
//-----------------------------------------------------------------------------
|
|
static byte texgammatable[256];
|
|
static uint lightgammatable[1024];
|
|
static uint lineargammatable[1024];
|
|
static uint screengammatable[1024];
|
|
static CVAR_DEFINE( v_direct, "direct", "0.9", 0, "direct studio lighting" );
|
|
static CVAR_DEFINE( v_texgamma, "texgamma", "2.0", 0, "texgamma amount" );
|
|
static CVAR_DEFINE( v_lightgamma, "lightgamma", "2.5", 0, "lightgamma amount" );
|
|
static CVAR_DEFINE( v_brightness, "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
|
|
static CVAR_DEFINE( v_gamma, "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
|
|
|
|
static void BuildGammaTable( const float gamma, const float brightness, const float texgamma, const float lightgamma )
|
|
{
|
|
float g1, g2, g3;
|
|
int i;
|
|
|
|
if( gamma != 0.0 )
|
|
g1 = 1.0 / gamma;
|
|
else g1 = 0.4;
|
|
|
|
g2 = g1 * texgamma;
|
|
|
|
if( brightness <= 0.0 )
|
|
g3 = 0.125;
|
|
else if( brightness <= 1.0 )
|
|
g3 = 0.125 - brightness * brightness * 0.075;
|
|
else
|
|
g3 = 0.05;
|
|
|
|
for( i = 0; i < 256; i++ )
|
|
{
|
|
double d = pow( i / 255.0, (double)g2 );
|
|
int inf = d * 255.0;
|
|
texgammatable[i] = bound( 0, inf, 255 );
|
|
}
|
|
|
|
for( i = 0; i < 1024; i++ )
|
|
{
|
|
double d;
|
|
float f = pow( i / 1023.0, (double)lightgamma );
|
|
int inf;
|
|
|
|
if( brightness > 1.0 )
|
|
f *= brightness;
|
|
|
|
if( f <= g3 )
|
|
f = ( f / g3 ) * 0.125;
|
|
else
|
|
f = (( f - g3 ) / ( 1.0 - g3 )) * 0.875 + 0.125;
|
|
|
|
d = pow( (double)f, (double)g1 ); // do not remove the cast, or tests fail
|
|
inf = d * 1023.0;
|
|
lightgammatable[i] = bound( 0, inf, 1023 );
|
|
|
|
// do these calculations in the same loop...
|
|
lineargammatable[i] = pow( i / 1023.0, (double)gamma ) * 1023.0;
|
|
screengammatable[i] = pow( i / 1023.0, 1.0 / gamma ) * 1023.0;
|
|
}
|
|
}
|
|
|
|
static void V_ValidateGammaCvars( void )
|
|
{
|
|
if( Host_IsLocalGame( ))
|
|
return;
|
|
|
|
if( v_gamma.value < 1.8f )
|
|
Cvar_DirectSet( &v_gamma, "1.8" );
|
|
else if( v_gamma.value > 3.0f )
|
|
Cvar_DirectSet( &v_gamma, "3" );
|
|
|
|
if( v_texgamma.value < 1.8f )
|
|
Cvar_DirectSet( &v_texgamma, "1.8" );
|
|
else if( v_texgamma.value > 3.0f )
|
|
Cvar_DirectSet( &v_texgamma, "3" );
|
|
|
|
if( v_lightgamma.value < 1.8f )
|
|
Cvar_DirectSet( &v_lightgamma, "1.8" );
|
|
else if( v_lightgamma.value > 3.0f )
|
|
Cvar_DirectSet( &v_lightgamma, "3" );
|
|
|
|
if( v_brightness.value < 0.0f )
|
|
Cvar_DirectSet( &v_brightness, "0" );
|
|
else if( v_brightness.value > 2.0f )
|
|
Cvar_DirectSet( &v_brightness, "2" );
|
|
}
|
|
|
|
void V_CheckGamma( void )
|
|
{
|
|
static qboolean dirty = false;
|
|
qboolean notify_refdll = false;
|
|
|
|
// because these cvars were defined as archive
|
|
// but wasn't doing anything useful
|
|
// reset them into default values
|
|
// this might be removed after a while
|
|
if( v_direct.value == 1.0f || v_lightgamma.value == 1.0f )
|
|
{
|
|
Cvar_DirectSet( &v_direct, "0.9" );
|
|
Cvar_DirectSet( &v_lightgamma, "2.5" );
|
|
}
|
|
|
|
if( cls.scrshot_action == scrshot_envshot || cls.scrshot_action == scrshot_skyshot )
|
|
{
|
|
dirty = true; // force recalculate next normal frame
|
|
BuildGammaTable( 1.8f, 0.0f, 2.0f, 2.5f );
|
|
if( ref.initialized )
|
|
ref.dllFuncs.R_GammaChanged( true );
|
|
return;
|
|
}
|
|
|
|
if( dirty || FBitSet( v_texgamma.flags|v_lightgamma.flags|v_brightness.flags|v_gamma.flags, FCVAR_CHANGED ))
|
|
{
|
|
V_ValidateGammaCvars();
|
|
|
|
dirty = false;
|
|
BuildGammaTable( v_gamma.value, v_brightness.value, v_texgamma.value, v_lightgamma.value );
|
|
|
|
// force refdll to recalculate lightmaps
|
|
notify_refdll = true;
|
|
|
|
// unfortunately, recalculating textures isn't possible yet
|
|
ClearBits( v_texgamma.flags, FCVAR_CHANGED );
|
|
ClearBits( v_lightgamma.flags, FCVAR_CHANGED );
|
|
ClearBits( v_brightness.flags, FCVAR_CHANGED );
|
|
ClearBits( v_gamma.flags, FCVAR_CHANGED );
|
|
}
|
|
|
|
if( notify_refdll && ref.initialized )
|
|
ref.dllFuncs.R_GammaChanged( false );
|
|
}
|
|
|
|
void V_Init( void )
|
|
{
|
|
Cvar_RegisterVariable( &v_texgamma );
|
|
Cvar_RegisterVariable( &v_lightgamma );
|
|
Cvar_RegisterVariable( &v_brightness );
|
|
Cvar_RegisterVariable( &v_gamma );
|
|
Cvar_RegisterVariable( &v_direct );
|
|
|
|
// force gamma init
|
|
SetBits( v_gamma.flags, FCVAR_CHANGED );
|
|
V_CheckGamma();
|
|
}
|
|
|
|
byte TextureToGamma( byte b )
|
|
{
|
|
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
|
|
return b;
|
|
|
|
return texgammatable[b];
|
|
}
|
|
|
|
byte LightToTexGamma( byte b )
|
|
{
|
|
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
|
|
return b;
|
|
|
|
// 255 << 2 is 1020, impossible to overflow
|
|
return lightgammatable[b << 2] >> 2;
|
|
}
|
|
|
|
uint LightToTexGammaEx( uint b )
|
|
{
|
|
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
|
|
return b;
|
|
|
|
if( unlikely( b > ARRAYSIZE( lightgammatable )))
|
|
return 0;
|
|
|
|
return lightgammatable[b];
|
|
}
|
|
|
|
uint ScreenGammaTable( uint b )
|
|
{
|
|
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
|
|
return b;
|
|
|
|
if( unlikely( b > ARRAYSIZE( screengammatable )))
|
|
return 0;
|
|
|
|
return screengammatable[b];
|
|
}
|
|
|
|
uint LinearGammaTable( uint b )
|
|
{
|
|
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
|
|
return b;
|
|
|
|
if( unlikely( b > ARRAYSIZE( lineargammatable )))
|
|
return 0;
|
|
return lineargammatable[b];
|
|
}
|