source-engine/materialsystem/colorspace.cpp

213 lines
4.4 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include <math.h>
#include "mathlib/bumpvects.h"
#include "colorspace.h"
#include "materialsystem_global.h"
#include "IHardwareConfigInternal.h"
#include "materialsystem/materialsystem_config.h"
// NOTE: This has to be the last file included
#include "tier0/memdbgon.h"
//static float texLightToLinear[256]; // texlight (0..255) to linear (0..4)
static float textureToLinear[256]; // texture (0..255) to linear (0..1)
static int linearToTexture[1024]; // linear (0..1) to texture (0..255)
static int linearToScreen[1024]; // linear (0..1) to gamma corrected vertex light (0..255)
float g_LinearToVertex[4096]; // linear (0..4) to screen corrected vertex space (0..1?)
static int linearToLightmap[4096]; // linear (0..4) to screen corrected texture value (0..255)
void ColorSpace::SetGamma( float screenGamma, float texGamma,
float overbright, bool allowCheats, bool linearFrameBuffer )
{
int i, inf;
float g1, g3;
float g;
float brightness = 0.0f; // This used to be configurable. . hardcode to 0.0
if( linearFrameBuffer )
{
screenGamma = 1.0f;
}
g = screenGamma;
// clamp values to prevent cheating in multiplayer
if( !allowCheats )
{
if (brightness > 2.0f)
brightness = 2.0f;
if (g < 1.8f)
g = 1.8f;
}
if (g > 3.0)
g = 3.0;
g = 1.0f / g;
g1 = texGamma * g;
// pow( textureColor, g1 ) converts from on-disk texture space to framebuffer space
if (brightness <= 0.0f)
{
g3 = 0.125;
}
else if (brightness > 1.0f)
{
g3 = 0.05f;
}
else
{
g3 = 0.125f - (brightness * brightness) * 0.075f;
}
for (i=0 ; i<1024 ; i++)
{
float f;
f = i / 1023.0f;
// scale up
if (brightness > 1.0f)
f = f * brightness;
// shift up
if (f <= g3)
f = (f / g3) * 0.125f;
else
f = 0.125f + ((f - g3) / (1.0f - g3)) * 0.875f;
// convert linear space to desired gamma space
inf = ( int )( 255 * pow ( f, g ) );
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
linearToScreen[i] = inf;
}
for (i=0 ; i<256 ; i++)
{
// convert from nonlinear texture space (0..255) to linear space (0..1)
textureToLinear[i] = ( float )pow( i / 255.0f, texGamma );
}
for (i=0 ; i<1024 ; i++)
{
// convert from linear space (0..1) to nonlinear texture space (0..255)
linearToTexture[i] = ( int )( pow( i / 1023.0f, 1.0f / texGamma ) * 255 );
}
#if 0
for (i=0 ; i<256 ; i++)
{
float f;
// convert from nonlinear lightmap space (0..255) to linear space (0..4)
f = ( float )( (i / 255.0f) * sqrt( 4 ) );
f = f * f;
texLightToLinear[i] = f;
}
#endif
float f, overbrightFactor;
// Can't do overbright without texcombine
// UNDONE: Add GAMMA ramp to rectify this
if ( !HardwareConfig() )
{
overbright = 1.0f;
}
if ( overbright == 2.0 )
{
overbrightFactor = 0.5;
}
else if ( overbright == 4.0 )
{
overbrightFactor = 0.25;
}
else
{
overbrightFactor = 1.0;
}
for (i=0 ; i<4096 ; i++)
{
// convert from linear 0..4 (x1024) to screen corrected vertex space (0..1?)
f = ( float )pow ( i/1024.0f, 1.0f / screenGamma );
g_LinearToVertex[i] = f * overbrightFactor;
if (g_LinearToVertex[i] > 1)
g_LinearToVertex[i] = 1;
linearToLightmap[i] = ( int )( f * 255 * overbrightFactor );
if (linearToLightmap[i] > 255)
linearToLightmap[i] = 255;
}
}
// convert texture to linear 0..1 value
float ColorSpace::TextureToLinear( int c )
{
if (c < 0)
return 0;
if (c > 255)
return 1.0f;
return textureToLinear[c];
}
// convert texture to linear 0..1 value
int ColorSpace::LinearToTexture( float f )
{
int i;
i = ( int )( f * 1023.0f ); // assume 0..1 range
if (i < 0)
i = 0;
if (i > 1023)
i = 1023;
return linearToTexture[i];
}
float ColorSpace::TexLightToLinear( int c, int exponent )
{
// return texLightToLinear[ c ];
// optimize me
return ( float )c * ( float )pow( 2.0f, exponent ) * ( 1.0f / 255.0f );
}
// converts 0..1 linear value to screen gamma (0..255)
int ColorSpace::LinearToScreenGamma( float f )
{
int i;
i = ( int )( f * 1023.0f ); // assume 0..1 range
if (i < 0)
i = 0;
if (i > 1023)
i = 1023;
return linearToScreen[i];
}
uint16 ColorSpace::LinearFloatToCorrectedShort( float in )
{
uint16 out;
in = min( in * 4096.0, 65535.0 );
out = max( in, 0.0f );
return out;
}