~a1batross/xash3d-fwgs

Gamma and overbrights v1 APPLIED

In this patchset I tried to mimic original GoldSrc rendering as much
accurately as possible. It also adds overbrights rendering (without
gl_vbo yet).

Compared to other gamma & overbrights attempts, I reverse-engineered
original gamma table generation function and how the gamma tables are
being applied to the textures and lightmaps.

The result is nearly indistinguishable from original Half-Life 1.
I also tried to compare the images with ImageMagick and while it finds
some exact pixels, most of the screenshots are pure noise and depend on
too much varaibles in the rendering process.

Alibek Omarov (18):
  ref: soft: remove vid_gamma/vid_brightness changed cvar value check
  ref: gl: remove vid_gamma/vid_brightness changed cvar value check
  ref: add R_GammaChanged function that engine calls on every gamma
    change
  engine: client: add new gamma implementation
  engine: client: add tests for new gamma implementation
  ref: gl: adapt studio lightning to new gamma
  ref: gl: support kRenderFxLightMultiplier
  ref: gl: don't depend on lightgamma in recursive light point
  ref: gl: support overbrights, change the gamma applying order closer
    to the original renderer
  ref: gl: adapt alias renderer to new gamma implementation (untested)
  engine: imagelib: apply texgamma to palette (ideally should be applied
    only to BSP/WAD textures)
  engine: remove cvar r_lighting_modulate, it's some unindentifiable
    legacy
  ref: gl: remove unused scale (remnants of r_lightmap_modulate), use
    integer values for non-interpolated lightstyles
  ref: soft: remove unused scale (remnants of r_lightmap_modulate), use
    integer values for non-interpolated lightstyles
  ref: soft: don't depend on light gamma in recursive light point
  ref: soft: adapt studio renderer to new gamma implementation
  ref: soft: reorder applying light gamma
  ref: gl: particles aren't supposed to care about gamma

 common/const.h                     |   1 +
 engine/client/cl_main.c            |   4 -
 engine/client/cl_scrn.c            |   2 +
 engine/client/cl_view.c            |   2 +
 engine/client/gamma.c              | 426 +++++++++++++++++++++++++++++
 engine/client/ref_common.c         |  25 +-
 engine/client/vid_common.c         |  18 +-
 engine/client/vid_common.h         |   1 -
 engine/common/common.h             |   7 +-
 engine/common/gamma.c              |  78 ------
 engine/common/imagelib/img_utils.c |   7 +-
 engine/common/tests.h              |   4 +-
 engine/platform/dos/vid_dos.c      |   2 -
 engine/platform/linux/vid_fbdev.c  |   2 -
 engine/platform/sdl/vid_sdl.c      |   5 +-
 engine/ref_api.h                   |  16 +-
 engine/server/sv_main.c            |   2 -
 engine/server/sv_phys.c            |   2 +-
 ref/gl/gl_alias.c                  |  18 +-
 ref/gl/gl_backend.c                |   2 -
 ref/gl/gl_context.c                |   1 +
 ref/gl/gl_local.h                  |   6 +-
 ref/gl/gl_rlight.c                 |  49 ++--
 ref/gl/gl_rmain.c                  |  17 +-
 ref/gl/gl_rpart.c                  |   4 +-
 ref/gl/gl_rsurf.c                  |  46 ++--
 ref/gl/gl_studio.c                 |  64 +++--
 ref/soft/r_context.c               |   1 +
 ref/soft/r_light.c                 |  46 ++--
 ref/soft/r_local.h                 |   4 +-
 ref/soft/r_main.c                  |  30 +-
 ref/soft/r_studio.c                |  68 +++--
 ref/soft/r_surf.c                  |  15 +-
 33 files changed, 644 insertions(+), 331 deletions(-)
 create mode 100644 engine/client/gamma.c
 delete mode 100644 engine/common/gamma.c

-- 
2.40.1
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~a1batross/xash3d-fwgs/patches/48370/mbox | git am -3
Learn more about email & git

[PATCH 01/18] ref: soft: remove vid_gamma/vid_brightness changed cvar value check Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/soft/r_main.c | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/ref/soft/r_main.c b/ref/soft/r_main.c
index d51e5cab..fb9d3f90 100644
--- a/ref/soft/r_main.c
+++ b/ref/soft/r_main.c
@@ -1643,28 +1643,6 @@ R_BeginFrame
*/
void GAME_EXPORT R_BeginFrame( qboolean clearScene )
{
#if 0 // unused
	if( R_DoResetGamma( ))
	{
		gEngfuncs.BuildGammaTable( 1.8f, 0.0f );
		D_FlushCaches( );

		// next frame will be restored gamma
		SetBits( vid_brightness->flags, FCVAR_CHANGED );
		SetBits( vid_gamma->flags, FCVAR_CHANGED );
	}
	else
#endif
	if( FBitSet( vid_gamma->flags, FCVAR_CHANGED ) || FBitSet( vid_brightness->flags, FCVAR_CHANGED ))
	{
		gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value );

		D_FlushCaches( );
		// next frame will be restored gamma
		ClearBits( vid_brightness->flags, FCVAR_CHANGED );
		ClearBits( vid_gamma->flags, FCVAR_CHANGED );
	}

	R_Set2DMode( true );

	// draw buffer stuff
-- 
2.40.1

[PATCH 02/18] ref: gl: remove vid_gamma/vid_brightness changed cvar value check Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_backend.c |  2 --
 ref/gl/gl_rmain.c   | 27 ---------------------------
 ref/gl/gl_rsurf.c   |  7 -------
 3 files changed, 36 deletions(-)

diff --git a/ref/gl/gl_backend.c b/ref/gl/gl_backend.c
index 1ca0b440..fc7434c0 100644
--- a/ref/gl/gl_backend.c
+++ b/ref/gl/gl_backend.c
@@ -560,8 +560,6 @@ qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qbo
	// use client vieworg
	if( !vieworg ) vieworg = RI.vieworg;

	R_CheckGamma();

	for( i = 0; i < 6; i++ )
	{
		// go into 3d mode
diff --git a/ref/gl/gl_rmain.c b/ref/gl/gl_rmain.c
index 6224d4e5..fc64695d 100644
--- a/ref/gl/gl_rmain.c
+++ b/ref/gl/gl_rmain.c
@@ -985,31 +985,6 @@ void R_RenderScene( void )
	R_EndGL();
}

/*
===============
R_CheckGamma
===============
*/
void R_CheckGamma( void )
{
	if( gEngfuncs.R_DoResetGamma( ))
	{
		// paranoia cubemaps uses this
		gEngfuncs.BuildGammaTable( 1.8f, 0.0f );

		// paranoia cubemap rendering
		if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
			gEngfuncs.drawFuncs->GL_BuildLightmaps( );
	}
	else if( FBitSet( vid_gamma->flags, FCVAR_CHANGED ) || FBitSet( vid_brightness->flags, FCVAR_CHANGED ))
	{
		gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value );
		glConfig.softwareGammaUpdate = true;
		GL_RebuildLightmaps();
		glConfig.softwareGammaUpdate = false;
	}
}

/*
===============
R_BeginFrame
@@ -1025,8 +1000,6 @@ void R_BeginFrame( qboolean clearScene )
		pglClear( GL_COLOR_BUFFER_BIT );
	}

	R_CheckGamma();

	R_Set2DMode( true );

	// draw buffer stuff
diff --git a/ref/gl/gl_rsurf.c b/ref/gl/gl_rsurf.c
index e237c659..04fb0245 100644
--- a/ref/gl/gl_rsurf.c
+++ b/ref/gl/gl_rsurf.c
@@ -3756,9 +3756,6 @@ void GL_RebuildLightmaps( void )
	if( !ENGINE_GET_PARM( PARM_CLIENT_ACTIVE ) )
		return; // wait for worldmodel

	ClearBits( vid_brightness->flags, FCVAR_CHANGED );
	ClearBits( vid_gamma->flags, FCVAR_CHANGED );

	// release old lightmaps
	for( i = 0; i < MAX_LIGHTMAPS; i++ )
	{
@@ -3874,10 +3871,6 @@ void GL_BuildLightmaps( void )
		// build lightmaps on the client-side
		gEngfuncs.drawFuncs->GL_BuildLightmaps( );
	}

	// now gamma and brightness are valid
	ClearBits( vid_brightness->flags, FCVAR_CHANGED );
	ClearBits( vid_gamma->flags, FCVAR_CHANGED );
}

void GL_InitRandomTable( void )
-- 
2.40.1

[PATCH 03/18] ref: add R_GammaChanged function that engine calls on every gamma change Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 engine/ref_api.h     |  1 +
 ref/gl/gl_context.c  |  1 +
 ref/gl/gl_local.h    |  2 +-
 ref/gl/gl_rmain.c    | 16 ++++++++++++++++
 ref/soft/r_context.c |  1 +
 ref/soft/r_local.h   |  1 +
 ref/soft/r_main.c    |  8 ++++++++
 7 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/engine/ref_api.h b/engine/ref_api.h
index 11c78a02..fbbefda6 100644
--- a/engine/ref_api.h
+++ b/engine/ref_api.h
@@ -463,6 +463,7 @@ typedef struct ref_interface_s
	void (*GL_ClearExtensions)( void );

	// scene rendering
	void (*R_GammaChanged)( qboolean do_reset_gamma );
	void (*R_BeginFrame)( qboolean clearScene );
	void (*R_RenderScene)( void );
	void (*R_EndFrame)( void );
diff --git a/ref/gl/gl_context.c b/ref/gl/gl_context.c
index dd665d90..db05733d 100644
--- a/ref/gl/gl_context.c
+++ b/ref/gl/gl_context.c
@@ -372,6 +372,7 @@ ref_interface_t gReffuncs =
	GL_InitExtensions,
	GL_ClearExtensions,

	R_GammaChanged,
	R_BeginFrame,
	R_RenderScene,
	R_EndFrame,
diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h
index d91044f2..0446a442 100644
--- a/ref/gl/gl_local.h
+++ b/ref/gl/gl_local.h
@@ -402,7 +402,6 @@ void R_AllowFog( qboolean allowed );
qboolean R_OpaqueEntity( cl_entity_t *ent );
void R_SetupFrustum( void );
void R_FindViewLeaf( void );
void R_CheckGamma( void );
void R_PushScene( void );
void R_PopScene( void );
void R_DrawFog( void );
@@ -534,6 +533,7 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
void GL_FreeImage( const char *name );
qboolean VID_ScreenShot( const char *filename, int shot_type );
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot );
void R_GammaChanged( qboolean do_reset_gamma );
void R_BeginFrame( qboolean clearScene );
void R_RenderFrame( const struct ref_viewpass_s *vp );
void R_EndFrame( void );
diff --git a/ref/gl/gl_rmain.c b/ref/gl/gl_rmain.c
index fc64695d..2a35a94f 100644
--- a/ref/gl/gl_rmain.c
+++ b/ref/gl/gl_rmain.c
@@ -985,6 +985,22 @@ void R_RenderScene( void )
	R_EndGL();
}

void R_GammaChanged( qboolean do_reset_gamma )
{
	if( do_reset_gamma )
	{
		// paranoia cubemap rendering
		if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
			gEngfuncs.drawFuncs->GL_BuildLightmaps( );
	}
	else
	{
		glConfig.softwareGammaUpdate = true;
		GL_RebuildLightmaps();
		glConfig.softwareGammaUpdate = false;
	}
}

/*
===============
R_BeginFrame
diff --git a/ref/soft/r_context.c b/ref/soft/r_context.c
index cac75f82..ecf3db2b 100644
--- a/ref/soft/r_context.c
+++ b/ref/soft/r_context.c
@@ -418,6 +418,7 @@ ref_interface_t gReffuncs =
	GL_InitExtensions,
	GL_ClearExtensions,

	R_GammaChanged,
	R_BeginFrame,
	R_RenderScene,
	R_EndFrame,
diff --git a/ref/soft/r_local.h b/ref/soft/r_local.h
index a9a918ce..1f2a1d5f 100644
--- a/ref/soft/r_local.h
+++ b/ref/soft/r_local.h
@@ -607,6 +607,7 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
void GL_FreeImage( const char *name );
qboolean VID_ScreenShot( const char *filename, int shot_type );
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot );
void R_GammaChanged( qboolean do_reset_gamma );
void R_BeginFrame( qboolean clearScene );
void R_RenderFrame( const struct ref_viewpass_s *vp );
void R_EndFrame( void );
diff --git a/ref/soft/r_main.c b/ref/soft/r_main.c
index fb9d3f90..2304b4cf 100644
--- a/ref/soft/r_main.c
+++ b/ref/soft/r_main.c
@@ -1636,6 +1636,14 @@ qboolean R_DoResetGamma( void )
#endif
}

void R_GammaChanged( qboolean do_reset_gamma )
{
	if( do_reset_gamma ) // unused
		return;

	D_FlushCaches( );
}

/*
===============
R_BeginFrame
-- 
2.40.1

[PATCH 04/18] engine: client: add new gamma implementation Export this patch

Immediately expose it in RefAPI. Bump RefAPI to version 7.
Remove VID_StartupGamma, it's not used anymore
Remove stub lightgamma and direct cvars

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 engine/client/cl_main.c           |   4 -
 engine/client/cl_scrn.c           |   2 +
 engine/client/cl_view.c           |   2 +
 engine/client/gamma.c             | 212 ++++++++++++++++++++++++++++++
 engine/client/ref_common.c        |  25 +---
 engine/client/vid_common.c        |  18 +--
 engine/client/vid_common.h        |   1 -
 engine/common/common.h            |   7 +-
 engine/common/gamma.c             |  78 -----------
 engine/platform/dos/vid_dos.c     |   2 -
 engine/platform/linux/vid_fbdev.c |   2 -
 engine/platform/sdl/vid_sdl.c     |   5 +-
 engine/ref_api.h                  |  14 +-
 13 files changed, 238 insertions(+), 134 deletions(-)
 create mode 100644 engine/client/gamma.c
 delete mode 100644 engine/common/gamma.c

diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c
index cfc4dafe..5ca07ef1 100644
--- a/engine/client/cl_main.c
+++ b/engine/client/cl_main.c
@@ -2922,10 +2922,6 @@ void CL_InitLocal( void )
	Cvar_RegisterVariable( &cl_maxframetime );
	Cvar_RegisterVariable( &cl_fixmodelinterpolationartifacts );

	// these two added to shut up CS 1.5 about 'unknown' commands
	Cvar_Get( "lightgamma", "1", FCVAR_ARCHIVE, "ambient lighting level (legacy, unused)" );
	Cvar_Get( "direct", "1", FCVAR_ARCHIVE, "direct lighting level (legacy, unused)" );

	// server commands
	Cmd_AddCommand ("noclip", NULL, "enable or disable no clipping mode" );
	Cmd_AddCommand ("notarget", NULL, "notarget mode (monsters do not see you)" );
diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c
index 4004a305..5145d735 100644
--- a/engine/client/cl_scrn.c
+++ b/engine/client/cl_scrn.c
@@ -292,6 +292,8 @@ void SCR_MakeScreenShot( void )
		viewsize = cls.envshot_viewsize;
	else viewsize = cl_envshot_size.value;

	V_CheckGamma();

	switch( cls.scrshot_action )
	{
	case scrshot_normal:
diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c
index f3fa4ca3..79f0bf7f 100644
--- a/engine/client/cl_view.c
+++ b/engine/client/cl_view.c
@@ -347,6 +347,8 @@ qboolean V_PreRender( void )
		return false;
	}

	V_CheckGamma();

	ref.dllFuncs.R_BeginFrame( !cl.paused && ( cls.state == ca_active ));

	GL_UpdateSwapInterval( );
diff --git a/engine/client/gamma.c b/engine/client/gamma.c
new file mode 100644
index 00000000..fbc3febc
--- /dev/null
+++ b/engine/client/gamma.c
@@ -0,0 +1,212 @@
/*
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 CVAR_DEFINE( gl_overbright, "gl_overbright", "1", FCVAR_ARCHIVE, "overbrights (ref_gl only)" );

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;

	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( FBitSet( gl_overbright.flags, FCVAR_CHANGED ))
	{
		// nothing to recalculate so far, just notify the refdll
		notify_refdll = true;
		ClearBits( gl_overbright.flags, FCVAR_CHANGED );
	}

	if( dirty || FBitSet( v_texgamma.flags|v_lightgamma.flags|v_brightness.flags|v_gamma.flags, FCVAR_CHANGED ))
	{
		V_ValidateGammaCvars();

		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 );
	Cvar_RegisterVariable( &gl_overbright );

	// 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];
}
diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c
index f68519eb..89f1211b 100644
--- a/engine/client/ref_common.c
+++ b/engine/client/ref_common.c
@@ -178,25 +178,6 @@ static screenfade_t *pfnRefGetScreenFade( void )
	return &clgame.fade;
}

/*
===============
R_DoResetGamma
gamma will be reset for
some type of screenshots
===============
*/
static qboolean R_DoResetGamma( void )
{
	switch( cls.scrshot_action )
	{
	case scrshot_envshot:
	case scrshot_skyshot:
		return true;
	default:
		return false;
	}
}

static qboolean R_Init_Video_( const int type )
{
	host.apply_opengl_config = true;
@@ -306,9 +287,11 @@ static ref_api_t gEngfuncs =
	SW_LockBuffer,
	SW_UnlockBuffer,

	BuildGammaTable,
	LightToTexGamma,
	R_DoResetGamma,
	LightToTexGammaEx,
	TextureToGamma,
	ScreenGammaTable,
	LinearGammaTable,

	CL_GetLightStyle,
	CL_GetDynamicLight,
diff --git a/engine/client/vid_common.c b/engine/client/vid_common.c
index 8038ff81..fcc29b92 100644
--- a/engine/client/vid_common.c
+++ b/engine/client/vid_common.c
@@ -22,8 +22,6 @@ GNU General Public License for more details.

static CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
static CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
static CVAR_DEFINE( vid_brightness, "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
static CVAR_DEFINE( vid_gamma, "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
static CVAR_DEFINE_AUTO( vid_mode, "0", FCVAR_RENDERINFO, "current video mode index (used only for storage)" );
static CVAR_DEFINE_AUTO( vid_rotate, "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
@@ -36,19 +34,6 @@ CVAR_DEFINE( window_ypos, "_window_ypos", "-1", FCVAR_RENDERINFO, "window positi

glwstate_t	glw_state;

/*
=================
VID_StartupGamma
=================
*/
void VID_StartupGamma( void )
{
	BuildGammaTable( vid_gamma.value, vid_brightness.value );
	Con_Reportf( "VID_StartupGamma: gamma %g brightness %g\n", vid_gamma.value, vid_brightness.value );
	ClearBits( vid_brightness.flags, FCVAR_CHANGED );
	ClearBits( vid_gamma.flags, FCVAR_CHANGED );
}

/*
=================
VID_InitDefaultResolution
@@ -224,8 +209,6 @@ void VID_Init( void )
	Cvar_RegisterVariable( &vid_scale );
	Cvar_RegisterVariable( &vid_fullscreen );
	Cvar_RegisterVariable( &vid_maximized );
	Cvar_RegisterVariable( &vid_brightness );
	Cvar_RegisterVariable( &vid_gamma );
	Cvar_RegisterVariable( &window_xpos );
	Cvar_RegisterVariable( &window_ypos );

@@ -233,5 +216,6 @@ void VID_Init( void )
	// but supported mode list is filled by backends, so numbers are not portable any more
	Cmd_AddRestrictedCommand( "vid_setmode", VID_Mode_f, "display video mode" );

	V_Init(); // init gamma
	R_Init(); // init renderer
}
diff --git a/engine/client/vid_common.h b/engine/client/vid_common.h
index 1f052f43..fc0bc08e 100644
--- a/engine/client/vid_common.h
+++ b/engine/client/vid_common.h
@@ -46,6 +46,5 @@ void R_SaveVideoMode( int w, int h, int render_w, int render_h, qboolean maximiz
void VID_SetDisplayTransform( int *render_w, int *render_h );
void VID_CheckChanges( void );
const char *VID_GetModeString( int vid_mode );
void VID_StartupGamma( void );

#endif // VID_COMMON
diff --git a/engine/common/common.h b/engine/common/common.h
index f6a240e1..b73a66b2 100644
--- a/engine/common/common.h
+++ b/engine/common/common.h
@@ -812,8 +812,13 @@ void S_StopBackgroundTrack( void );
void S_StopAllSounds( qboolean ambient );

// gamma routines
void BuildGammaTable( float gamma, float brightness );
byte LightToTexGamma( byte b );
byte TextureToGamma( byte );
uint LightToTexGammaEx( uint );
uint ScreenGammaTable( uint );
uint LinearGammaTable( uint );
void V_Init( void );
void V_CheckGamma( void );

//
// identification.c
diff --git a/engine/common/gamma.c b/engine/common/gamma.c
deleted file mode 100644
index aac4a6c4..00000000
--- a/engine/common/gamma.c
@@ -1,78 +0,0 @@
/*
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 "xash3d_mathlib.h"
#include "enginefeatures.h"

//-----------------------------------------------------------------------------
// Gamma conversion support
//-----------------------------------------------------------------------------
static byte	lightgammatable[256];
static int	lineargammatable[1024];
static int	screengammatable[1024];

void BuildGammaTable( float lightgamma, float brightness )
{
	int	i, inf;
	float	f, g, g1, g3;

	lightgamma = bound( 1.8f, lightgamma, 3.0f );
	brightness = bound( 0.0f, brightness, 10.0f );

	if( brightness <= 0.0f )
		g3 = 0.125f;
	else if( brightness > 1.0f )
		g3 = 0.05f;
	else g3 = 0.125f - (brightness * brightness) * 0.075f;

	g = 1.0f / lightgamma;
	g1 = GAMMA * g;

	for( i = 0; i < 256; i++ )
	{
		f = pow( i / 255.f, GAMMA );

		// 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.0f * pow( f, g ));

		lightgammatable[i] = bound( 0, inf, 255 );
	}

	for( i = 0; i < 1024; i++ )
	{
		// convert from screen gamma space to linear space
		lineargammatable[i] = 1023 * pow( i / 1023.0f, g1 );

		// convert from linear gamma space to screen space
		screengammatable[i] = 1023 * pow( i / 1023.0f, 1.0f / g1 );
	}
}

byte LightToTexGamma( byte b )
{
	if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
		return b;
	else
		return lightgammatable[b];
}
diff --git a/engine/platform/dos/vid_dos.c b/engine/platform/dos/vid_dos.c
index fe0ecf6a..833567ce 100644
--- a/engine/platform/dos/vid_dos.c
+++ b/engine/platform/dos/vid_dos.c
@@ -48,8 +48,6 @@ qboolean  R_Init_Video( const int type )
{
	qboolean retval;

	VID_StartupGamma();

	if( type != REF_SOFTWARE )
		return false; /// glide???

diff --git a/engine/platform/linux/vid_fbdev.c b/engine/platform/linux/vid_fbdev.c
index b6b0e16b..9a7e7aa0 100644
--- a/engine/platform/linux/vid_fbdev.c
+++ b/engine/platform/linux/vid_fbdev.c
@@ -51,8 +51,6 @@ qboolean  R_Init_Video( const int type )
	string fbdev = DEFAULT_FBDEV;
	fb.fd = -1;

	VID_StartupGamma();

	if( type != REF_SOFTWARE )
		return false;

diff --git a/engine/platform/sdl/vid_sdl.c b/engine/platform/sdl/vid_sdl.c
index 0a58353a..54ef7a89 100644
--- a/engine/platform/sdl/vid_sdl.c
+++ b/engine/platform/sdl/vid_sdl.c
@@ -843,13 +843,10 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
					return false;
				GL_SetupAttributes(); // re-choose attributes
			}

			VID_StartupGamma();
		}

		if( !GL_UpdateContext( ))
		return false;

			return false;
	}

#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
diff --git a/engine/ref_api.h b/engine/ref_api.h
index fbbefda6..2edefdbc 100644
--- a/engine/ref_api.h
+++ b/engine/ref_api.h
@@ -42,7 +42,8 @@ GNU General Public License for more details.
// 6. Removed timing from ref_globals_t.
//    Renderers are supposed to migrate to ref_client_t/ref_host_t using PARM_GET_CLIENT_PTR and PARM_GET_HOST_PTR
//    Removed functions to get internal engine structions. Use PARM_GET_*_PTR instead.
#define REF_API_VERSION 6
// 7. Gamma fixes.
#define REF_API_VERSION 7


#define TF_SKY		(TF_SKYSIDE|TF_NOMIPMAP)
@@ -404,9 +405,11 @@ typedef struct ref_api_s
	void (*SW_UnlockBuffer)( void );

	// gamma
	void (*BuildGammaTable)( float lightgamma, float brightness );
	byte		(*LightToTexGamma)( byte color );	// software gamma support
	qboolean	(*R_DoResetGamma)( void );
	byte (*LightToTexGamma)( byte );	// software gamma support
	uint (*LightToTexGammaEx)( uint );	// software gamma support
	byte (*TextureToGamma)( byte );
	uint (*ScreenGammaTable)( uint );
	uint (*LinearGammaTable)( uint );

	// renderapi
	lightstyle_t*	(*GetLightStyle)( int number );
@@ -652,6 +655,8 @@ typedef int (*REFAPI)( int version, ref_interface_t *pFunctionTable, ref_api_t*
#define ENGINE_SHARED_CVAR_LIST( f ) \
	ENGINE_SHARED_CVAR_NAME( f, vid_gamma, gamma ) \
	ENGINE_SHARED_CVAR_NAME( f, vid_brightness, brightness ) \
	ENGINE_SHARED_CVAR_NAME( f, v_lightgamma, lightgamma ) \
	ENGINE_SHARED_CVAR_NAME( f, v_direct, direct ) \
	ENGINE_SHARED_CVAR( f, r_showtextures ) \
	ENGINE_SHARED_CVAR( f, r_speeds ) \
	ENGINE_SHARED_CVAR( f, r_fullbright ) \
@@ -663,6 +668,7 @@ typedef int (*REFAPI)( int version, ref_interface_t *pFunctionTable, ref_api_t*
	ENGINE_SHARED_CVAR( f, r_showhull ) \
	ENGINE_SHARED_CVAR( f, gl_vsync ) \
	ENGINE_SHARED_CVAR( f, gl_clear ) \
	ENGINE_SHARED_CVAR( f, gl_overbright ) \
	ENGINE_SHARED_CVAR( f, cl_himodels ) \
	ENGINE_SHARED_CVAR( f, cl_lightstyle_lerping ) \
	ENGINE_SHARED_CVAR( f, tracerred ) \
-- 
2.40.1

[PATCH 05/18] engine: client: add tests for new gamma implementation Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 engine/client/gamma.c | 214 ++++++++++++++++++++++++++++++++++++++++++
 engine/common/tests.h |   4 +-
 2 files changed, 217 insertions(+), 1 deletion(-)

diff --git a/engine/client/gamma.c b/engine/client/gamma.c
index fbc3febc..89d741c5 100644
--- a/engine/client/gamma.c
+++ b/engine/client/gamma.c
@@ -210,3 +210,217 @@ uint LinearGammaTable( uint b )
		return 0;
	return lineargammatable[b];
}

#if XASH_ENGINE_TESTS
#include "tests.h"

typedef struct precomputed_gamma_tables_s
{
	float gamma;
	float brightness;
	float texgamma;
	float lightgamma;
	byte  texgammatable[256];
	int   lightgammatable[1024];
	int   lineargammatable[1024];
	int   screengammatable[1024];
} precomputed_gamma_tables_t;

// put at the end of the file, to not confuse Qt Creator's parser
precomputed_gamma_tables_t *Test_GetGammaTables( int i );

static void Test_PrecomputedGammaTables( void )
{
	precomputed_gamma_tables_t *data;
	int i = 0;

	while(( data = Test_GetGammaTables( i )))
	{
		int j;

		BuildGammaTable( data->gamma, data->brightness, data->texgamma, data->lightgamma );

		for( j = 0; j < 1024; j++ )
		{
			if( j < 256 )
			{
				TASSERT_EQi( texgammatable[j], data->texgammatable[j] );
			}

			TASSERT_EQi( lightgammatable[j], data->lightgammatable[j] );
			TASSERT_EQi( lineargammatable[j], data->lineargammatable[j] );
			TASSERT_EQi( screengammatable[j], data->screengammatable[j] );
		}
		i++;
	}
}

void Test_RunGamma( void )
{
	TRUN( Test_PrecomputedGammaTables() );
}

precomputed_gamma_tables_t *Test_GetGammaTables( int i )
{
	static precomputed_gamma_tables_t precomputed_data[] = {
	{
		.gamma = 2.5,
		.brightness = 0.0,
		.texgamma = 2.0,
		.lightgamma = 2.5,
		.texgammatable = {
			0, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 20, 22, 23, 25, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41, 42, 43, 44, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84,
			85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 132, 133, 134, 135, 136, 137, 138,
			139, 140, 141, 142, 143, 144, 145, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 165, 166, 167, 168, 169, 170, 171, 172, 172, 173, 174, 175, 176, 177, 178, 179, 180, 180, 181, 182, 183, 184, 185,
			186, 186, 187, 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, 197, 198, 198, 199, 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 214, 215, 216, 217, 218, 219, 219, 220, 221, 222, 223, 224, 224, 225, 226, 227, 228, 229,
			229, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 238, 239, 240, 241, 242, 242, 243, 244, 245, 246, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, 255
		},
		.lightgammatable = {
			0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
			65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
			124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
			176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
			228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
			280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
			332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 343, 343, 344, 345, 346, 347, 348, 349, 350, 351, 353, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 376, 376, 377, 379, 379, 380, 381, 382, 383,
			384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435,
			436, 437, 438, 439, 440, 441, 442, 443, 444, 446, 446, 447, 449, 449, 450, 451, 452, 453, 455, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 468, 469, 470, 470, 472, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487,
			488, 489, 490, 491, 493, 493, 494, 495, 496, 498, 498, 499, 500, 502, 502, 503, 504, 505, 507, 508, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 520, 521, 521, 522, 523, 524, 525, 526, 527, 528, 530, 530, 531, 532, 533, 534, 536, 536, 537, 538, 539,
			540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 552, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 564, 564, 565, 566, 567, 568, 570, 571, 571, 572, 573, 574, 576, 576, 577, 578, 579, 580, 581, 583, 583, 584, 585, 586, 587, 588, 590, 591, 591,
			593, 593, 594, 596, 596, 597, 598, 600, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 611, 611, 612, 613, 615, 615, 616, 618, 618, 620, 621, 621, 622, 624, 625, 626, 627, 627, 628, 629, 630, 632, 633, 633, 634, 635, 636, 638, 638, 639, 641, 642, 643, 643,
			644, 645, 646, 648, 648, 650, 651, 651, 652, 654, 655, 656, 656, 658, 658, 660, 660, 662, 662, 664, 664, 665, 666, 668, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 682, 682, 683, 684, 685, 686, 687, 688, 690, 690, 691, 692, 693, 695, 696,
			696, 697, 698, 699, 700, 701, 702, 703, 705, 706, 706, 707, 708, 709, 710, 711, 712, 713, 715, 716, 716, 717, 718, 719, 721, 721, 722, 724, 724, 725, 727, 727, 728, 729, 730, 731, 733, 733, 734, 735, 736, 737, 738, 740, 740, 741, 743, 744, 744, 745, 747, 747,
			748, 749, 750, 752, 753, 753, 755, 755, 757, 757, 758, 759, 760, 761, 762, 764, 764, 766, 766, 767, 769, 770, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 782, 783, 784, 784, 785, 786, 788, 789, 790, 791, 792, 792, 794, 794, 796, 796, 797, 799, 800,
			801, 801, 802, 803, 804, 805, 806, 807, 809, 810, 810, 811, 813, 813, 815, 815, 816, 817, 819, 819, 820, 822, 823, 823, 824, 825, 826, 827, 829, 829, 830, 832, 832, 833, 835, 835, 837, 837, 839, 840, 840, 841, 842, 843, 844, 845, 847, 847, 849, 849, 850, 851,
			852, 854, 854, 856, 856, 857, 859, 859, 860, 861, 862, 864, 864, 865, 867, 867, 868, 870, 870, 872, 872, 874, 875, 875, 876, 877, 879, 880, 881, 881, 882, 883, 885, 885, 886, 887, 888, 890, 891, 891, 893, 893, 894, 895, 897, 898, 899, 900, 901, 902, 902, 903,
			904, 905, 907, 907, 908, 910, 910, 911, 912, 914, 914, 915, 917, 918, 919, 920, 921, 922, 922, 923, 925, 925, 926, 927, 928, 930, 931, 932, 932, 933, 935, 936, 936, 937, 939, 940, 940, 942, 942, 944, 944, 946, 947, 948, 949, 949, 950, 952, 952, 953, 955, 956,
			957, 958, 959, 959, 960, 962, 962, 964, 965, 965, 967, 967, 969, 970, 971, 972, 973, 973, 975, 975, 976, 977, 978, 979, 980, 982, 982, 984, 984, 986, 986, 988, 988, 990, 991, 992, 993, 993, 994, 995, 996, 998, 999, 999, 1000, 1002, 1002, 1004, 1005, 1005,
			1006, 1007, 1008, 1010, 1011, 1011, 1013, 1014, 1015, 1016, 1017, 1018, 1018, 1019, 1020, 1021, 1023
		},
		.lineargammatable = {
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
			2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11,
			11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 25, 25,
			25, 25, 26, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46,
			47, 47, 48, 48, 48, 49, 49, 50, 50, 50, 51, 51, 52, 52, 52, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76,
			77, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 92, 93, 94, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111, 111, 112,
			113, 113, 114, 115, 115, 116, 117, 117, 118, 119, 119, 120, 121, 122, 122, 123, 124, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131, 132, 132, 133, 134, 134, 135, 136, 137, 137, 138, 139, 140, 140, 141, 142, 143, 144, 144, 145, 146, 147, 147, 148, 149, 150,
			151, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 164, 164, 165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 174, 175, 176, 176, 177, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 193, 194,
			195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
			247, 248, 249, 250, 251, 252, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 267, 268, 269, 270, 271, 272, 274, 275, 276, 277, 278, 279, 280, 282, 283, 284, 285, 286, 287, 289, 290, 291, 292, 293, 294, 296, 297, 298, 299, 300, 302, 303, 304, 305,
			306, 308, 309, 310, 311, 312, 314, 315, 316, 317, 319, 320, 321, 322, 324, 325, 326, 327, 329, 330, 331, 333, 334, 335, 336, 338, 339, 340, 342, 343, 344, 345, 347, 348, 349, 351, 352, 353, 355, 356, 357, 359, 360, 361, 363, 364, 365, 367, 368, 369, 371, 372,
			373, 375, 376, 378, 379, 380, 382, 383, 384, 386, 387, 389, 390, 391, 393, 394, 396, 397, 399, 400, 401, 403, 404, 406, 407, 409, 410, 411, 413, 414, 416, 417, 419, 420, 422, 423, 425, 426, 428, 429, 431, 432, 434, 435, 437, 438, 440, 441, 443, 444, 446, 447,
			449, 450, 452, 453, 455, 456, 458, 459, 461, 462, 464, 466, 467, 469, 470, 472, 473, 475, 477, 478, 480, 481, 483, 485, 486, 488, 489, 491, 493, 494, 496, 497, 499, 501, 502, 504, 506, 507, 509, 511, 512, 514, 515, 517, 519, 520, 522, 524, 525, 527, 529, 531,
			532, 534, 536, 537, 539, 541, 542, 544, 546, 548, 549, 551, 553, 554, 556, 558, 560, 561, 563, 565, 567, 568, 570, 572, 574, 575, 577, 579, 581, 583, 584, 586, 588, 590, 592, 593, 595, 597, 599, 601, 602, 604, 606, 608, 610, 612, 613, 615, 617, 619, 621, 623,
			625, 626, 628, 630, 632, 634, 636, 638, 639, 641, 643, 645, 647, 649, 651, 653, 655, 657, 659, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724,
			726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 753, 755, 757, 759, 761, 763, 765, 767, 769, 771, 773, 776, 778, 780, 782, 784, 786, 788, 791, 793, 795, 797, 799, 801, 803, 806, 808, 810, 812, 814, 816, 819, 821, 823, 825, 827, 830, 832, 834,
			836, 839, 841, 843, 845, 847, 850, 852, 854, 856, 859, 861, 863, 865, 868, 870, 872, 874, 877, 879, 881, 884, 886, 888, 890, 893, 895, 897, 900, 902, 904, 907, 909, 911, 914, 916, 918, 921, 923, 925, 928, 930, 932, 935, 937, 940, 942, 944, 947, 949, 952, 954,
			956, 959, 961, 964, 966, 968, 971, 973, 976, 978, 981, 983, 985, 988, 990, 993, 995, 998, 1000, 1003, 1005, 1008, 1010, 1013, 1015, 1018, 1020, 1023
		},
		.screengammatable = {
			0, 63, 84, 99, 111, 121, 130, 139, 146, 154, 160, 166, 172, 178, 183, 188, 193, 198, 203, 207, 212, 216, 220, 224, 228, 231, 235, 239, 242, 245, 249, 252, 255, 259, 262, 265, 268, 271, 274, 276, 279, 282, 285, 287, 290, 293, 295, 298, 300, 303, 305, 308,
			310, 313, 315, 317, 320, 322, 324, 326, 328, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 370, 372, 374, 376, 378, 379, 381, 383, 385, 386, 388, 390, 392, 393, 395, 397, 398, 400, 401, 403, 405, 406, 408,
			409, 411, 413, 414, 416, 417, 419, 420, 422, 423, 425, 426, 428, 429, 431, 432, 434, 435, 436, 438, 439, 441, 442, 444, 445, 446, 448, 449, 450, 452, 453, 455, 456, 457, 459, 460, 461, 463, 464, 465, 466, 468, 469, 470, 472, 473, 474, 475, 477, 478, 479, 480,
			482, 483, 484, 485, 487, 488, 489, 490, 491, 493, 494, 495, 496, 497, 499, 500, 501, 502, 503, 504, 505, 507, 508, 509, 510, 511, 512, 513, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539,
			540, 541, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 585, 586, 587, 588, 589, 590,
			591, 592, 593, 594, 595, 595, 596, 597, 598, 599, 600, 601, 602, 603, 603, 604, 605, 606, 607, 608, 609, 610, 610, 611, 612, 613, 614, 615, 616, 616, 617, 618, 619, 620, 621, 622, 622, 623, 624, 625, 626, 627, 627, 628, 629, 630, 631, 632, 632, 633, 634, 635,
			636, 637, 637, 638, 639, 640, 641, 641, 642, 643, 644, 645, 645, 646, 647, 648, 649, 649, 650, 651, 652, 652, 653, 654, 655, 656, 656, 657, 658, 659, 659, 660, 661, 662, 663, 663, 664, 665, 666, 666, 667, 668, 669, 669, 670, 671, 672, 672, 673, 674, 675, 675,
			676, 677, 678, 678, 679, 680, 681, 681, 682, 683, 684, 684, 685, 686, 686, 687, 688, 689, 689, 690, 691, 692, 692, 693, 694, 694, 695, 696, 697, 697, 698, 699, 699, 700, 701, 701, 702, 703, 704, 704, 705, 706, 706, 707, 708, 708, 709, 710, 711, 711, 712, 713,
			713, 714, 715, 715, 716, 717, 717, 718, 719, 719, 720, 721, 721, 722, 723, 723, 724, 725, 725, 726, 727, 727, 728, 729, 729, 730, 731, 731, 732, 733, 733, 734, 735, 735, 736, 737, 737, 738, 739, 739, 740, 741, 741, 742, 743, 743, 744, 745, 745, 746, 746, 747,
			748, 748, 749, 750, 750, 751, 752, 752, 753, 753, 754, 755, 755, 756, 757, 757, 758, 758, 759, 760, 760, 761, 762, 762, 763, 763, 764, 765, 765, 766, 767, 767, 768, 768, 769, 770, 770, 771, 771, 772, 773, 773, 774, 774, 775, 776, 776, 777, 778, 778, 779, 779,
			780, 781, 781, 782, 782, 783, 784, 784, 785, 785, 786, 786, 787, 788, 788, 789, 789, 790, 791, 791, 792, 792, 793, 794, 794, 795, 795, 796, 796, 797, 798, 798, 799, 799, 800, 801, 801, 802, 802, 803, 803, 804, 805, 805, 806, 806, 807, 807, 808, 809, 809, 810,
			810, 811, 811, 812, 813, 813, 814, 814, 815, 815, 816, 816, 817, 818, 818, 819, 819, 820, 820, 821, 821, 822, 823, 823, 824, 824, 825, 825, 826, 826, 827, 828, 828, 829, 829, 830, 830, 831, 831, 832, 832, 833, 834, 834, 835, 835, 836, 836, 837, 837, 838, 838,
			839, 839, 840, 841, 841, 842, 842, 843, 843, 844, 844, 845, 845, 846, 846, 847, 848, 848, 849, 849, 850, 850, 851, 851, 852, 852, 853, 853, 854, 854, 855, 855, 856, 856, 857, 857, 858, 859, 859, 860, 860, 861, 861, 862, 862, 863, 863, 864, 864, 865, 865, 866,
			866, 867, 867, 868, 868, 869, 869, 870, 870, 871, 871, 872, 872, 873, 873, 874, 874, 875, 875, 876, 876, 877, 877, 878, 878, 879, 879, 880, 880, 881, 881, 882, 882, 883, 883, 884, 884, 885, 885, 886, 886, 887, 887, 888, 888, 889, 889, 890, 890, 891, 891, 892,
			892, 893, 893, 894, 894, 895, 895, 896, 896, 897, 897, 898, 898, 899, 899, 900, 900, 901, 901, 902, 902, 903, 903, 904, 904, 904, 905, 905, 906, 906, 907, 907, 908, 908, 909, 909, 910, 910, 911, 911, 912, 912, 913, 913, 914, 914, 915, 915, 915, 916, 916, 917,
			917, 918, 918, 919, 919, 920, 920, 921, 921, 922, 922, 922, 923, 923, 924, 924, 925, 925, 926, 926, 927, 927, 928, 928, 929, 929, 929, 930, 930, 931, 931, 932, 932, 933, 933, 934, 934, 935, 935, 935, 936, 936, 937, 937, 938, 938, 939, 939, 940, 940, 940, 941,
			941, 942, 942, 943, 943, 944, 944, 944, 945, 945, 946, 946, 947, 947, 948, 948, 949, 949, 949, 950, 950, 951, 951, 952, 952, 953, 953, 953, 954, 954, 955, 955, 956, 956, 957, 957, 957, 958, 958, 959, 959, 960, 960, 961, 961, 961, 962, 962, 963, 963, 964, 964,
			964, 965, 965, 966, 966, 967, 967, 968, 968, 968, 969, 969, 970, 970, 971, 971, 971, 972, 972, 973, 973, 974, 974, 974, 975, 975, 976, 976, 977, 977, 977, 978, 978, 979, 979, 980, 980, 980, 981, 981, 982, 982, 983, 983, 983, 984, 984, 985, 985, 986, 986, 986,
			987, 987, 988, 988, 988, 989, 989, 990, 990, 991, 991, 991, 992, 992, 993, 993, 993, 994, 994, 995, 995, 996, 996, 996, 997, 997, 998, 998, 998, 999, 999, 1000, 1000, 1001, 1001, 1001, 1002, 1002, 1003, 1003, 1003, 1004, 1004, 1005, 1005, 1005, 1006, 1006,
			1007, 1007, 1008, 1008, 1008, 1009, 1009, 1010, 1010, 1010, 1011, 1011, 1012, 1012, 1012, 1013, 1013, 1014, 1014, 1014, 1015, 1015, 1016, 1016, 1016, 1017, 1017, 1018, 1018, 1018, 1019, 1019, 1020, 1020, 1020, 1021, 1021, 1022, 1022, 1023
		},
	}, {
		.gamma = 2.2,
		.brightness = 1.0,
		.texgamma = 2.2,
		.lightgamma = 2.4,
		.texgammatable = {
			0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
			66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
			124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
			176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
			228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
		},
		.lightgammatable = {
			0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 52, 53, 55, 56, 57, 58, 60, 61, 62, 63, 65, 66, 67, 69, 70, 71, 72, 74, 75, 76,
			78, 79, 80, 81, 83, 84, 85, 87, 88, 89, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 114, 116, 117, 118, 120, 121, 122, 124, 125, 126, 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 147, 148, 149,
			151, 152, 153, 155, 156, 157, 159, 160, 162, 163, 164, 166, 167, 168, 170, 171, 173, 174, 175, 177, 178, 179, 181, 182, 184, 185, 186, 188, 189, 191, 192, 193, 195, 196, 198, 199, 200, 202, 203, 204, 206, 207, 209, 210, 211, 213, 214, 216, 217, 219, 220, 221,
			223, 224, 226, 227, 228, 230, 231, 233, 234, 235, 237, 238, 240, 241, 243, 244, 245, 247, 248, 250, 251, 252, 254, 255, 257, 258, 260, 261, 262, 264, 265, 267, 268, 270, 271, 272, 274, 275, 277, 278, 280, 281, 282, 284, 285, 287, 288, 290, 291, 293, 294, 295,
			297, 298, 300, 301, 303, 304, 306, 307, 308, 310, 311, 313, 314, 316, 317, 319, 320, 321, 323, 324, 326, 327, 329, 330, 332, 333, 335, 336, 337, 339, 340, 342, 343, 345, 346, 348, 349, 351, 352, 354, 355, 356, 358, 359, 361, 362, 364, 365, 367, 368, 370, 371,
			373, 374, 376, 377, 378, 380, 381, 383, 384, 386, 387, 389, 390, 392, 393, 395, 396, 397, 398, 398, 399, 399, 400, 401, 401, 402, 402, 403, 403, 404, 404, 405, 406, 406, 407, 407, 408, 408, 409, 410, 410, 411, 411, 412, 413, 413, 414, 414, 415, 416, 416, 417,
			417, 418, 419, 419, 420, 420, 421, 422, 422, 423, 423, 424, 425, 425, 426, 427, 427, 428, 428, 429, 430, 430, 431, 432, 432, 433, 433, 434, 435, 435, 436, 437, 437, 438, 439, 439, 440, 441, 441, 442, 443, 443, 444, 445, 445, 446, 447, 447, 448, 449, 449, 450,
			451, 451, 452, 453, 453, 454, 455, 455, 456, 457, 457, 458, 459, 459, 460, 461, 461, 462, 463, 464, 464, 465, 466, 466, 467, 468, 468, 469, 470, 471, 471, 472, 473, 473, 474, 475, 476, 476, 477, 478, 478, 479, 480, 481, 481, 482, 483, 483, 484, 485, 486, 486,
			487, 488, 489, 489, 490, 491, 492, 492, 493, 494, 495, 495, 496, 497, 498, 498, 499, 500, 501, 501, 502, 503, 504, 504, 505, 506, 507, 507, 508, 509, 510, 510, 511, 512, 513, 513, 514, 515, 516, 517, 517, 518, 519, 520, 520, 521, 522, 523, 524, 524, 525, 526,
			527, 527, 528, 529, 530, 531, 531, 532, 533, 534, 535, 535, 536, 537, 538, 538, 539, 540, 541, 542, 542, 543, 544, 545, 546, 546, 547, 548, 549, 550, 550, 551, 552, 553, 554, 555, 555, 556, 557, 558, 559, 559, 560, 561, 562, 563, 564, 564, 565, 566, 567, 568,
			568, 569, 570, 571, 572, 573, 573, 574, 575, 576, 577, 578, 578, 579, 580, 581, 582, 583, 583, 584, 585, 586, 587, 588, 588, 589, 590, 591, 592, 593, 593, 594, 595, 596, 597, 598, 599, 599, 600, 601, 602, 603, 604, 605, 605, 606, 607, 608, 609, 610, 611, 611,
			612, 613, 614, 615, 616, 617, 617, 618, 619, 620, 621, 622, 623, 623, 624, 625, 626, 627, 628, 629, 629, 630, 631, 632, 633, 634, 635, 636, 636, 637, 638, 639, 640, 641, 642, 643, 643, 644, 645, 646, 647, 648, 649, 650, 651, 651, 652, 653, 654, 655, 656, 657,
			658, 658, 659, 660, 661, 662, 663, 664, 665, 666, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 703,
			704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 749, 750, 751,
			752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 795, 796, 797, 798, 799, 800,
			801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850,
			851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 900,
			901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952,
			953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002,
			1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1023
		},
		.lineargammatable = {
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
			4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
			17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36,
			36, 36, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 42, 42, 42, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 47, 47, 48, 48, 48, 49, 49, 50, 50, 51, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 61, 62, 62, 63,
			63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 82, 82, 83, 83, 84, 84, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 97, 98, 99,
			99, 100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111, 111, 112, 113, 113, 114, 115, 115, 116, 117, 117, 118, 119, 119, 120, 121, 121, 122, 123, 123, 124, 125, 126, 126, 127, 128, 128, 129, 130, 131, 131, 132, 133, 133,
			134, 135, 136, 136, 137, 138, 139, 139, 140, 141, 142, 142, 143, 144, 145, 145, 146, 147, 148, 148, 149, 150, 151, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 171, 172, 172, 173, 174,
			175, 176, 177, 177, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
			222, 223, 224, 225, 226, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
			274, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 288, 289, 290, 291, 292, 293, 294, 295, 296, 298, 299, 300, 301, 302, 303, 304, 305, 307, 308, 309, 310, 311, 312, 313, 315, 316, 317, 318, 319, 320, 322, 323, 324, 325, 326, 328, 329, 330, 331, 332,
			333, 335, 336, 337, 338, 339, 341, 342, 343, 344, 346, 347, 348, 349, 350, 352, 353, 354, 355, 357, 358, 359, 360, 362, 363, 364, 365, 367, 368, 369, 370, 372, 373, 374, 375, 377, 378, 379, 381, 382, 383, 384, 386, 387, 388, 390, 391, 392, 393, 395, 396, 397,
			399, 400, 401, 403, 404, 405, 407, 408, 409, 411, 412, 413, 415, 416, 417, 419, 420, 421, 423, 424, 426, 427, 428, 430, 431, 432, 434, 435, 437, 438, 439, 441, 442, 443, 445, 446, 448, 449, 450, 452, 453, 455, 456, 458, 459, 460, 462, 463, 465, 466, 468, 469,
			470, 472, 473, 475, 476, 478, 479, 481, 482, 483, 485, 486, 488, 489, 491, 492, 494, 495, 497, 498, 500, 501, 503, 504, 506, 507, 509, 510, 512, 513, 515, 516, 518, 519, 521, 522, 524, 525, 527, 528, 530, 532, 533, 535, 536, 538, 539, 541, 542, 544, 545, 547,
			549, 550, 552, 553, 555, 556, 558, 560, 561, 563, 564, 566, 568, 569, 571, 572, 574, 576, 577, 579, 580, 582, 584, 585, 587, 589, 590, 592, 593, 595, 597, 598, 600, 602, 603, 605, 607, 608, 610, 612, 613, 615, 617, 618, 620, 622, 623, 625, 627, 628, 630, 632,
			633, 635, 637, 639, 640, 642, 644, 645, 647, 649, 650, 652, 654, 656, 657, 659, 661, 663, 664, 666, 668, 670, 671, 673, 675, 677, 678, 680, 682, 684, 685, 687, 689, 691, 692, 694, 696, 698, 700, 701, 703, 705, 707, 709, 710, 712, 714, 716, 718, 719, 721, 723,
			725, 727, 729, 730, 732, 734, 736, 738, 740, 741, 743, 745, 747, 749, 751, 753, 754, 756, 758, 760, 762, 764, 766, 767, 769, 771, 773, 775, 777, 779, 781, 783, 785, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 809, 811, 813, 815, 817, 819, 821,
			823, 825, 827, 829, 831, 833, 835, 837, 839, 841, 843, 845, 847, 849, 851, 853, 855, 857, 859, 861, 863, 865, 867, 869, 871, 873, 875, 877, 879, 881, 883, 885, 887, 889, 891, 893, 895, 897, 899, 901, 903, 905, 907, 910, 912, 914, 916, 918, 920, 922, 924, 926,
			928, 930, 932, 934, 937, 939, 941, 943, 945, 947, 949, 951, 953, 956, 958, 960, 962, 964, 966, 968, 970, 973, 975, 977, 979, 981, 983, 985, 988, 990, 992, 994, 996, 998, 1001, 1003, 1005, 1007, 1009, 1012, 1014, 1016, 1018, 1020, 1023
		},
		.screengammatable = {
			0, 43, 60, 72, 82, 91, 98, 106, 112, 118, 124, 130, 135, 140, 145, 150, 154, 158, 163, 167, 171, 174, 178, 182, 185, 189, 192, 196, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 228, 231, 234, 237, 239, 242, 244, 247, 249, 252, 254, 257, 259, 261,
			264, 266, 268, 270, 273, 275, 277, 279, 281, 283, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 311, 313, 315, 317, 319, 321, 323, 324, 326, 328, 330, 331, 333, 335, 337, 338, 340, 342, 343, 345, 347, 348, 350, 352, 353, 355, 357, 358, 360,
			361, 363, 365, 366, 368, 369, 371, 372, 374, 375, 377, 378, 380, 381, 383, 384, 386, 387, 389, 390, 392, 393, 394, 396, 397, 399, 400, 401, 403, 404, 406, 407, 408, 410, 411, 412, 414, 415, 416, 418, 419, 420, 422, 423, 424, 426, 427, 428, 430, 431, 432, 433,
			435, 436, 437, 438, 440, 441, 442, 443, 445, 446, 447, 448, 450, 451, 452, 453, 454, 456, 457, 458, 459, 460, 462, 463, 464, 465, 466, 467, 469, 470, 471, 472, 473, 474, 475, 477, 478, 479, 480, 481, 482, 483, 484, 486, 487, 488, 489, 490, 491, 492, 493, 494,
			495, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 545, 546, 547,
			548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 583, 584, 585, 586, 587, 588, 589, 590, 591, 591, 592, 593, 594, 595,
			596, 597, 598, 598, 599, 600, 601, 602, 603, 604, 604, 605, 606, 607, 608, 609, 609, 610, 611, 612, 613, 614, 615, 615, 616, 617, 618, 619, 620, 620, 621, 622, 623, 624, 624, 625, 626, 627, 628, 629, 629, 630, 631, 632, 633, 633, 634, 635, 636, 637, 637, 638,
			639, 640, 641, 641, 642, 643, 644, 645, 645, 646, 647, 648, 649, 649, 650, 651, 652, 652, 653, 654, 655, 656, 656, 657, 658, 659, 659, 660, 661, 662, 663, 663, 664, 665, 666, 666, 667, 668, 669, 669, 670, 671, 672, 672, 673, 674, 675, 675, 676, 677, 678, 678,
			679, 680, 681, 681, 682, 683, 684, 684, 685, 686, 686, 687, 688, 689, 689, 690, 691, 692, 692, 693, 694, 694, 695, 696, 697, 697, 698, 699, 700, 700, 701, 702, 702, 703, 704, 705, 705, 706, 707, 707, 708, 709, 709, 710, 711, 712, 712, 713, 714, 714, 715, 716,
			716, 717, 718, 719, 719, 720, 721, 721, 722, 723, 723, 724, 725, 725, 726, 727, 728, 728, 729, 730, 730, 731, 732, 732, 733, 734, 734, 735, 736, 736, 737, 738, 738, 739, 740, 740, 741, 742, 742, 743, 744, 744, 745, 746, 746, 747, 748, 748, 749, 750, 750, 751,
			752, 752, 753, 754, 754, 755, 756, 756, 757, 758, 758, 759, 759, 760, 761, 761, 762, 763, 763, 764, 765, 765, 766, 767, 767, 768, 769, 769, 770, 770, 771, 772, 772, 773, 774, 774, 775, 776, 776, 777, 777, 778, 779, 779, 780, 781, 781, 782, 782, 783, 784, 784,
			785, 786, 786, 787, 787, 788, 789, 789, 790, 791, 791, 792, 792, 793, 794, 794, 795, 795, 796, 797, 797, 798, 799, 799, 800, 800, 801, 802, 802, 803, 803, 804, 805, 805, 806, 806, 807, 808, 808, 809, 809, 810, 811, 811, 812, 812, 813, 814, 814, 815, 815, 816,
			817, 817, 818, 818, 819, 820, 820, 821, 821, 822, 823, 823, 824, 824, 825, 825, 826, 827, 827, 828, 828, 829, 830, 830, 831, 831, 832, 833, 833, 834, 834, 835, 835, 836, 837, 837, 838, 838, 839, 839, 840, 841, 841, 842, 842, 843, 843, 844, 845, 845, 846, 846,
			847, 847, 848, 849, 849, 850, 850, 851, 851, 852, 853, 853, 854, 854, 855, 855, 856, 857, 857, 858, 858, 859, 859, 860, 860, 861, 862, 862, 863, 863, 864, 864, 865, 865, 866, 867, 867, 868, 868, 869, 869, 870, 870, 871, 872, 872, 873, 873, 874, 874, 875, 875,
			876, 876, 877, 878, 878, 879, 879, 880, 880, 881, 881, 882, 882, 883, 884, 884, 885, 885, 886, 886, 887, 887, 888, 888, 889, 889, 890, 891, 891, 892, 892, 893, 893, 894, 894, 895, 895, 896, 896, 897, 898, 898, 899, 899, 900, 900, 901, 901, 902, 902, 903, 903,
			904, 904, 905, 905, 906, 906, 907, 908, 908, 909, 909, 910, 910, 911, 911, 912, 912, 913, 913, 914, 914, 915, 915, 916, 916, 917, 917, 918, 918, 919, 920, 920, 921, 921, 922, 922, 923, 923, 924, 924, 925, 925, 926, 926, 927, 927, 928, 928, 929, 929, 930, 930,
			931, 931, 932, 932, 933, 933, 934, 934, 935, 935, 936, 936, 937, 937, 938, 938, 939, 939, 940, 940, 941, 941, 942, 942, 943, 943, 944, 944, 945, 945, 946, 946, 947, 947, 948, 948, 949, 949, 950, 950, 951, 951, 952, 952, 953, 953, 954, 954, 955, 955, 956, 956,
			957, 957, 958, 958, 959, 959, 960, 960, 961, 961, 962, 962, 963, 963, 964, 964, 965, 965, 966, 966, 967, 967, 968, 968, 969, 969, 969, 970, 970, 971, 971, 972, 972, 973, 973, 974, 974, 975, 975, 976, 976, 977, 977, 978, 978, 979, 979, 980, 980, 981, 981, 982,
			982, 982, 983, 983, 984, 984, 985, 985, 986, 986, 987, 987, 988, 988, 989, 989, 990, 990, 991, 991, 991, 992, 992, 993, 993, 994, 994, 995, 995, 996, 996, 997, 997, 998, 998, 999, 999, 999, 1000, 1000, 1001, 1001, 1002, 1002, 1003, 1003, 1004, 1004, 1005,
			1005, 1006, 1006, 1006, 1007, 1007, 1008, 1008, 1009, 1009, 1010, 1010, 1011, 1011, 1012, 1012, 1012, 1013, 1013, 1014, 1014, 1015, 1015, 1016, 1016, 1017, 1017, 1017, 1018, 1018, 1019, 1019, 1020, 1020, 1021, 1021, 1022, 1022, 1023
		},
	}
	};

	if( i < 0 || i >= ARRAYSIZE( precomputed_data ))
		return NULL;

	return &precomputed_data[i];
}
#endif
diff --git a/engine/common/tests.h b/engine/common/tests.h
index a88b6b22..48c06551 100644
--- a/engine/common/tests.h
+++ b/engine/common/tests.h
@@ -38,6 +38,7 @@ void Test_RunCvar( void );
void Test_RunCon( void );
void Test_RunVOX( void );
void Test_RunIPFilter( void );
void Test_RunGamma( void );

#define TEST_LIST_0 \
	Test_RunLibCommon(); \
@@ -47,7 +48,8 @@ void Test_RunIPFilter( void );
	Test_RunIPFilter();

#define TEST_LIST_0_CLIENT \
	Test_RunCon();
	Test_RunCon(); \
	Test_RunGamma();

#define TEST_LIST_1 \
	Test_RunImagelib();
-- 
2.40.1

[PATCH 06/18] ref: gl: adapt studio lightning to new gamma Export this patch

* more accurate SHADE_LAMBERT value (extracted from v_lambert1 global variable)

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_local.h  |  2 +-
 ref/gl/gl_studio.c | 55 +++++++++++++++++++++++++++-------------------
 ref/soft/r_local.h |  2 +-
 3 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h
index 0446a442..9181adc5 100644
--- a/ref/gl/gl_local.h
+++ b/ref/gl/gl_local.h
@@ -76,7 +76,7 @@ extern poolhandle_t r_temppool;
#define MAX_DRAW_STACK	2		// normal view and menu view

#define SHADEDOT_QUANT 	16		// precalculated dot products for quantized angles
#define SHADE_LAMBERT	1.495f
#define SHADE_LAMBERT	1.4953241
#define DEFAULT_ALPHATEST	0.0f

// refparams
diff --git a/ref/gl/gl_studio.c b/ref/gl/gl_studio.c
index ad09a6c9..8932ae51 100644
--- a/ref/gl/gl_studio.c
+++ b/ref/gl/gl_studio.c
@@ -103,7 +103,7 @@ typedef struct
	int		numlocallights;
	int		lightage[MAXSTUDIOBONES];
	dlight_t		*locallight[MAX_LOCALLIGHTS];
	color24		locallightcolor[MAX_LOCALLIGHTS];
	int		locallightcolor[MAX_LOCALLIGHTS][3];
	vec4_t		lightpos[MAXSTUDIOVERTS][MAX_LOCALLIGHTS];
	vec3_t		lightbonepos[MAXSTUDIOBONES][MAX_LOCALLIGHTS];
	float		locallightR2[MAX_LOCALLIGHTS];
@@ -1381,13 +1381,13 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )
		{
			VectorSet( lightDir, mv->skyvec_x, mv->skyvec_y, mv->skyvec_z );

			light.r = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_r, 255 ));
			light.g = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_g, 255 ));
			light.b = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_b, 255 ));
			light.r = mv->skycolor_r;
			light.g = mv->skycolor_g;
			light.b = mv->skycolor_b;
		}
	}

	if(( light.r + light.g + light.b ) < 16 ) // TESTTEST
	if(( light.r + light.g + light.b ) == 0 )
	{
		colorVec	gcolor;
		float	grad[4];
@@ -1466,15 +1466,15 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )

			VectorAdd( lightDir, dist, lightDir );

			finalLight[0] += gEngfuncs.LightToTexGamma( dl->color.r ) * ( add / 256.0f ) * 2.0f;
			finalLight[1] += gEngfuncs.LightToTexGamma( dl->color.g ) * ( add / 256.0f ) * 2.0f;
			finalLight[2] += gEngfuncs.LightToTexGamma( dl->color.b ) * ( add / 256.0f ) * 2.0f;
			finalLight[0] += dl->color.r * ( add / 256.0f );
			finalLight[1] += dl->color.g * ( add / 256.0f );
			finalLight[2] += dl->color.b * ( add / 256.0f );
		}
	}

	if( FBitSet( ent->model->flags, STUDIO_AMBIENT_LIGHT ))
		add = 0.6f;
	else add = 0.9f;
	else add = bound( 0.75f, v_direct->value, 1.0f );

	VectorScale( lightDir, add, lightDir );

@@ -1568,9 +1568,9 @@ void R_StudioEntityLight( alight_t *lightinfo )

			if( k != -1 )
			{
				g_studio.locallightcolor[k].r = gEngfuncs.LightToTexGamma( el->color.r );
				g_studio.locallightcolor[k].g = gEngfuncs.LightToTexGamma( el->color.g );
				g_studio.locallightcolor[k].b = gEngfuncs.LightToTexGamma( el->color.b );
				g_studio.locallightcolor[k][0] = gEngfuncs.LinearGammaTable( el->color.r << 2 );
				g_studio.locallightcolor[k][1] = gEngfuncs.LinearGammaTable( el->color.g << 2 );
				g_studio.locallightcolor[k][2] = gEngfuncs.LinearGammaTable( el->color.b << 2 );
				g_studio.locallightR2[k] = r2;
				g_studio.locallight[k] = el;
				lstrength[k] = minstrength;
@@ -1665,7 +1665,8 @@ void R_StudioLighting( float *lv, int bone, int flags, vec3_t normal )
	}

	illum = Q_min( illum, 255.0f );
	*lv = illum * (1.0f / 255.0f);

	*lv = gEngfuncs.LightToTexGammaEx( illum * 4 ) / 1023.0f;
}

/*
@@ -1685,7 +1686,7 @@ static void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], const vec3_t normal,
		return;
	}

	VectorCopy( color, finalLight );
	VectorSet( finalLight, 0, 0, 0 );

	for( i = 0; i < g_studio.numlocallights; i++ )
	{
@@ -1709,21 +1710,29 @@ static void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], const vec3_t normal,
				else light[i][3] = 0.0001f;
			}

			temp = Q_min( r * light[i][3] / 255.0f, 1.0f );

			localLight[0] = (float)g_studio.locallightcolor[i].r * temp;
			localLight[1] = (float)g_studio.locallightcolor[i].g * temp;
			localLight[2] = (float)g_studio.locallightcolor[i].b * temp;
			temp = r * light[i][3];

			VectorAddScalar( g_studio.locallightcolor[i], temp, localLight );
			VectorAdd( finalLight, localLight, finalLight );
		}
	}

	VectorScale( finalLight, 255.0f, finalLight );
	if( !VectorIsNull( finalLight ))
	{
		for( i = 0; i < 3; i++ )
		{
			float c = finalLight[i] + gEngfuncs.LinearGammaTable( color[i] * 1023.0f );

	out[0] = Q_min( (int)( finalLight[0] ), 255 );
	out[1] = Q_min( (int)( finalLight[1] ), 255 );
	out[2] = Q_min( (int)( finalLight[2] ), 255 );
			if( c > 1023.0f )
				out[i] = 255;
			else
				out[i] = gEngfuncs.ScreenGammaTable( c ) >> 2;
		}
	}
	else
	{
		VectorScale( color, 255.0f, out );
	}
}

static void R_StudioSetColorArray( short *ptricmds, vec3_t *pstudionorms, byte *color )
diff --git a/ref/soft/r_local.h b/ref/soft/r_local.h
index 1f2a1d5f..74ffb6b4 100644
--- a/ref/soft/r_local.h
+++ b/ref/soft/r_local.h
@@ -66,7 +66,7 @@ extern poolhandle_t r_temppool;
#define MAX_DRAW_STACK	2		// normal view and menu view

#define SHADEDOT_QUANT 	16		// precalculated dot products for quantized angles
#define SHADE_LAMBERT	1.495f
#define SHADE_LAMBERT	1.4953241
#define DEFAULT_ALPHATEST	0.0f

// refparams
-- 
2.40.1

[PATCH 07/18] ref: gl: support kRenderFxLightMultiplier Export this patch

* add undocumented kRenderFxLightMultiplier to const.h

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 common/const.h     | 1 +
 ref/gl/gl_studio.c | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/common/const.h b/common/const.h
index a7e3d08b..fe4469fa 100644
--- a/common/const.h
+++ b/common/const.h
@@ -717,6 +717,7 @@ enum
	kRenderFxExplode,			// Scale up really big!
	kRenderFxGlowShell,			// Glowing Shell
	kRenderFxClampMinScale,		// Keep this sprite from getting very small (SPRITES only!)
	kRenderFxLightMultiplier,
};

typedef int		func_t;
diff --git a/ref/gl/gl_studio.c b/ref/gl/gl_studio.c
index 8932ae51..2b3de57b 100644
--- a/ref/gl/gl_studio.c
+++ b/ref/gl/gl_studio.c
@@ -1435,6 +1435,13 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )
		}
	}

	if( ent->curstate.renderfx == kRenderFxLightMultiplier && ent->curstate.iuser4 != 10 )
	{
		light.r *= ent->curstate.iuser4 / 10.0f;
		light.g *= ent->curstate.iuser4 / 10.0f;
		light.b *= ent->curstate.iuser4 / 10.0f;
	}

	VectorSet( finalLight, light.r, light.g, light.b );
	ent->cvFloorColor = light;

-- 
2.40.1

[PATCH 08/18] ref: gl: don't depend on lightgamma in recursive light point Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_local.h  |  2 --
 ref/gl/gl_rlight.c | 23 ++++++++---------------
 ref/gl/gl_studio.c |  2 --
 3 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h
index 9181adc5..311838c0 100644
--- a/ref/gl/gl_local.h
+++ b/ref/gl/gl_local.h
@@ -238,7 +238,6 @@ typedef struct
	int		realframecount;	// not including viewpasses
	int		framecount;

	qboolean		ignore_lightgamma;
	qboolean		fCustomRendering;
	qboolean		fResetVis;
	qboolean		fFlipViewModel;
@@ -528,7 +527,6 @@ void GL_SetupAttributes( int safegl );
void GL_OnContextCreated( void );
void GL_InitExtensions( void );
void GL_ClearExtensions( void );
void VID_CheckChanges( void );
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
void GL_FreeImage( const char *name );
qboolean VID_ScreenShot( const char *filename, int shot_type );
diff --git a/ref/gl/gl_rlight.c b/ref/gl/gl_rlight.c
index d97439ad..c2f208ae 100644
--- a/ref/gl/gl_rlight.c
+++ b/ref/gl/gl_rlight.c
@@ -320,18 +320,10 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
		{
			uint	scale = tr.lightstylevalue[surf->styles[map]];

			if( tr.ignore_lightgamma )
			{
				cv->r += lm->r * scale;
				cv->g += lm->g * scale;
				cv->b += lm->b * scale;
			}
			else
			{
				cv->r += gEngfuncs.LightToTexGamma( lm->r ) * scale;
				cv->g += gEngfuncs.LightToTexGamma( lm->g ) * scale;
				cv->b += gEngfuncs.LightToTexGamma( lm->b ) * scale;
			}
			cv->r += lm->r * scale;
			cv->g += lm->g * scale;
			cv->b += lm->b * scale;

			lm += size; // skip to next lightmap

			if( dm != NULL )
@@ -418,9 +410,10 @@ colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot,
			{
				if( lspot ) VectorCopy( g_trace_lightspot, lspot );
				if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
				light.r = Q_min(( cv.r >> 7 ), 255 );
				light.g = Q_min(( cv.g >> 7 ), 255 );
				light.b = Q_min(( cv.b >> 7 ), 255 );

				light.r = Q_min(( cv.r >> 8 ), 255 );
				light.g = Q_min(( cv.g >> 8 ), 255 );
				light.b = Q_min(( cv.b >> 8 ), 255 );
				last_fraction = g_trace_fraction;

				if(( light.r + light.g + light.b ) != 0 )
diff --git a/ref/gl/gl_studio.c b/ref/gl/gl_studio.c
index 2b3de57b..d2d30b84 100644
--- a/ref/gl/gl_studio.c
+++ b/ref/gl/gl_studio.c
@@ -3661,9 +3661,7 @@ void R_GatherPlayerLight( void )
	cl_entity_t	*view = tr.viewent;
	colorVec		c;

	tr.ignore_lightgamma = true;
	c = R_LightPoint( view->origin );
	tr.ignore_lightgamma = false;
	gEngfuncs.SetLocalLightLevel( ( c.r + c.g + c.b ) / 3 );
}

-- 
2.40.1

[PATCH 09/18] ref: gl: support overbrights, change the gamma applying order closer to the original renderer Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_rsurf.c | 39 +++++++++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/ref/gl/gl_rsurf.c b/ref/gl/gl_rsurf.c
index 04fb0245..3aedb141 100644
--- a/ref/gl/gl_rsurf.c
+++ b/ref/gl/gl_rsurf.c
@@ -600,9 +600,9 @@ void R_AddDynamicLights( msurface_t *surf )

				if( dist < minlight )
				{
					bl[0] += ((int)((rad - dist) * 256) * gEngfuncs.LightToTexGamma( dl->color.r )) / 256;
					bl[1] += ((int)((rad - dist) * 256) * gEngfuncs.LightToTexGamma( dl->color.g )) / 256;
					bl[2] += ((int)((rad - dist) * 256) * gEngfuncs.LightToTexGamma( dl->color.b )) / 256;
					bl[0] += ((int)((rad - dist) * 256) * dl->color.r ) / 256;
					bl[1] += ((int)((rad - dist) * 256) * dl->color.g ) / 256;
					bl[2] += ((int)((rad - dist) * 256) * dl->color.b ) / 256;
				}
			}
		}
@@ -742,11 +742,15 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean
	int		sample_size;
	mextrasurf_t	*info = surf->info;
	color24		*lm;
	int lightscale;

	sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
	smax = ( info->lightextents[0] / sample_size ) + 1;
	tmax = ( info->lightextents[1] / sample_size ) + 1;
	size = smax * tmax;
	if( gl_overbright->value )
		lightscale = 256;
	else lightscale = ( pow( 2.0f, 1.0f / v_lightgamma->value ) * 256 ) + 0.5;

	lm = surf->samples;

@@ -759,9 +763,9 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean

		for( i = 0, bl = r_blocklights; i < size; i++, bl += 3, lm++ )
		{
			bl[0] += gEngfuncs.LightToTexGamma( lm->r ) * scale;
			bl[1] += gEngfuncs.LightToTexGamma( lm->g ) * scale;
			bl[2] += gEngfuncs.LightToTexGamma( lm->b ) * scale;
			bl[0] += lm->r * scale;
			bl[1] += lm->g * scale;
			bl[2] += lm->b * scale;
		}
	}

@@ -777,9 +781,16 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean
	{
		for( s = 0; s < smax; s++ )
		{
			dest[0] = Q_min((bl[0] >> 7), 255 );
			dest[1] = Q_min((bl[1] >> 7), 255 );
			dest[2] = Q_min((bl[2] >> 7), 255 );
			int i;
			for( i = 0; i < 3; i++ )
			{
				int t = bl[i] * lightscale >> 14;

				if( t > 1023 )
					t = 1023;

				dest[i] = gEngfuncs.LightToTexGammaEx( t ) >> 2;
			}
			dest[3] = 255;

			bl += 3;
@@ -944,7 +955,15 @@ void R_BlendLightmaps( void )
	pglDepthFunc( GL_EQUAL );

	pglDisable( GL_ALPHA_TEST );
	pglBlendFunc( GL_ZERO, GL_SRC_COLOR );
	if( gl_overbright->value )
	{
		pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR );
		pglColor4f( 128.0f / 192.0f, 128.0f / 192.0f, 128.0f / 192.0f, 1.0f );
	}
	else
	{
		pglBlendFunc( GL_ZERO, GL_SRC_COLOR );
	}
	pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	// render static lightmaps first
-- 
2.40.1

[PATCH 10/18] ref: gl: adapt alias renderer to new gamma implementation (untested) Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_alias.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/ref/gl/gl_alias.c b/ref/gl/gl_alias.c
index d12d32b8..fc077532 100644
--- a/ref/gl/gl_alias.c
+++ b/ref/gl/gl_alias.c
@@ -822,9 +822,9 @@ void R_AliasDynamicLight( cl_entity_t *ent, alight_t *plight )
		{
			VectorSet( lightDir, mv->skyvec_x, mv->skyvec_y, mv->skyvec_z );

			light.r = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_r, 255 ));
			light.g = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_g, 255 ));
			light.b = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_b, 255 ));
			light.r = mv->skycolor_r;
			light.g = mv->skycolor_g;
			light.b = mv->skycolor_b;
		}
	}

@@ -907,9 +907,9 @@ void R_AliasDynamicLight( cl_entity_t *ent, alight_t *plight )

			VectorAdd( lightDir, dist, lightDir );

			finalLight[0] += gEngfuncs.LightToTexGamma( dl->color.r ) * ( add / 256.0f ) * 2.0f;
			finalLight[1] += gEngfuncs.LightToTexGamma( dl->color.g ) * ( add / 256.0f ) * 2.0f;
			finalLight[2] += gEngfuncs.LightToTexGamma( dl->color.b ) * ( add / 256.0f ) * 2.0f;
			finalLight[0] += dl->color.r * ( add / 256.0f );
			finalLight[1] += dl->color.g * ( add / 256.0f );
			finalLight[2] += dl->color.b * ( add / 256.0f );
		}
	}

@@ -991,9 +991,9 @@ void R_AliasLighting( float *lv, const vec3_t normal )
			illum -= g_alias.shadelight * lightcos;
	}

	illum = Q_max( illum, 0.0f );
	illum = Q_min( illum, 255.0f );
	*lv = illum * (1.0f / 255.0f);
	illum = bound( 0.0f, illum, 255.0f );

	*lv = gEngfuncs.LightToTexGammaEx( illum * 4 ) / 1023.0f;
}

/*
-- 
2.40.1

[PATCH 11/18] engine: imagelib: apply texgamma to palette (ideally should be applied only to BSP/WAD textures) Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 engine/common/imagelib/img_utils.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/engine/common/imagelib/img_utils.c b/engine/common/imagelib/img_utils.c
index 29107e65..3fa0a43f 100644
--- a/engine/common/imagelib/img_utils.c
+++ b/engine/common/imagelib/img_utils.c
@@ -287,16 +287,15 @@ void Image_SetPalette( const byte *pal, uint *d_table )
	uint uirgba; // TODO: palette looks byte-swapped on big-endian
	int	i;


	// setup palette
	switch( image.d_rendermode )
	{
	case LUMP_NORMAL:
		for( i = 0; i < 256; i++ )
		{
			rgba[0] = pal[i*3+0];
			rgba[1] = pal[i*3+1];
			rgba[2] = pal[i*3+2];
			rgba[0] = TextureToGamma( pal[i*3+0] );
			rgba[1] = TextureToGamma( pal[i*3+1] );
			rgba[2] = TextureToGamma( pal[i*3+2] );
			rgba[3] = 0xFF;
			memcpy( &uirgba, rgba, sizeof( uirgba ));
			d_table[i] = uirgba;
-- 
2.40.1

[PATCH 12/18] engine: remove cvar r_lighting_modulate, it's some unindentifiable legacy Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 engine/ref_api.h        | 1 -
 engine/server/sv_main.c | 2 --
 engine/server/sv_phys.c | 2 +-
 ref/gl/gl_rlight.c      | 2 +-
 ref/soft/r_light.c      | 2 +-
 5 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/engine/ref_api.h b/engine/ref_api.h
index 2edefdbc..42c5e041 100644
--- a/engine/ref_api.h
+++ b/engine/ref_api.h
@@ -679,7 +679,6 @@ typedef int (*REFAPI)( int version, ref_interface_t *pFunctionTable, ref_api_t*
	ENGINE_SHARED_CVAR( f, r_sprite_lighting ) \
	ENGINE_SHARED_CVAR( f, r_drawviewmodel ) \
	ENGINE_SHARED_CVAR( f, r_glowshellfreq ) \
	ENGINE_SHARED_CVAR( f, r_lighting_modulate ) \

#define DECLARE_ENGINE_SHARED_CVAR_LIST() \
	ENGINE_SHARED_CVAR_LIST( DECLARE_ENGINE_SHARED_CVAR )
diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c
index aaa3dea7..5a67303d 100644
--- a/engine/server/sv_main.c
+++ b/engine/server/sv_main.c
@@ -129,7 +129,6 @@ CVAR_DEFINE( public_server, "public", "0", 0, "change server type from private t
CVAR_DEFINE_AUTO( sv_novis, "0", 0, "force to ignore server visibility" );			// disable server culling entities by vis
CVAR_DEFINE( sv_pausable, "pausable", "1", FCVAR_SERVER, "allow players to pause or not" );
static CVAR_DEFINE_AUTO( timeout, "125", FCVAR_SERVER, "connection timeout" );				// seconds without any message
CVAR_DEFINE( sv_lighting_modulate, "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" );
CVAR_DEFINE( sv_maxclients, "maxplayers", "1", FCVAR_LATCH, "server max capacity" );
CVAR_DEFINE_AUTO( sv_check_errors, "0", FCVAR_ARCHIVE, "check edicts for errors" );
CVAR_DEFINE_AUTO( sv_reconnect_limit, "3", FCVAR_ARCHIVE, "max reconnect attempts" );		// minimum seconds between connect messages
@@ -919,7 +918,6 @@ void SV_Init( void )
	Cvar_RegisterVariable( &sv_maxclients );
	Cvar_RegisterVariable( &sv_check_errors );
	Cvar_RegisterVariable( &public_server );
	Cvar_RegisterVariable( &sv_lighting_modulate );
	Cvar_RegisterVariable( &sv_reconnect_limit );
	Cvar_RegisterVariable( &sv_failuretime );
	Cvar_RegisterVariable( &sv_unlag );
diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c
index 8e152cb4..9e49fd42 100644
--- a/engine/server/sv_phys.c
+++ b/engine/server/sv_phys.c
@@ -1784,7 +1784,7 @@ static void SV_RunLightStyles( void )
	lightstyle_t	*ls;
	float		scale;

	scale = sv_lighting_modulate.value;
	scale = 1.0f;

	// run lightstyles animation
	for( i = 0, ls = sv.lightstyles; i < MAX_LIGHTSTYLES; i++, ls++ )
diff --git a/ref/gl/gl_rlight.c b/ref/gl/gl_rlight.c
index c2f208ae..5c47916f 100644
--- a/ref/gl/gl_rlight.c
+++ b/ref/gl/gl_rlight.c
@@ -42,7 +42,7 @@ void CL_RunLightStyles( void )

	if( !WORLDMODEL ) return;

	scale = r_lighting_modulate->value;
	scale = 1.0f;

	// light animations
	// 'm' is normal light, 'a' is no light, 'z' is double bright
diff --git a/ref/soft/r_light.c b/ref/soft/r_light.c
index 07ca2c8d..6b029cd5 100644
--- a/ref/soft/r_light.c
+++ b/ref/soft/r_light.c
@@ -45,7 +45,7 @@ void GAME_EXPORT CL_RunLightStyles( void )

	if( !WORLDMODEL ) return;

	scale = 1; //r_lighting_modulate->value;
	scale = 1.0f;

	// light animations
	// 'm' is normal light, 'a' is no light, 'z' is double bright
-- 
2.40.1

[PATCH 13/18] ref: gl: remove unused scale (remnants of r_lightmap_modulate), use integer values for non-interpolated lightstyles Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_rlight.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/ref/gl/gl_rlight.c b/ref/gl/gl_rlight.c
index 5c47916f..ac31decc 100644
--- a/ref/gl/gl_rlight.c
+++ b/ref/gl/gl_rlight.c
@@ -36,24 +36,24 @@ void CL_RunLightStyles( void )
{
	int		i, k, flight, clight;
	float		l, lerpfrac, backlerp;
	float		frametime = (gp_cl->time -   gp_cl->oldtime);
	float		scale;
	float		frametime = (gp_cl->time - gp_cl->oldtime);
	lightstyle_t	*ls;

	if( !WORLDMODEL ) return;
	if( !WORLDMODEL )
		return;

	scale = 1.0f;
	if( !WORLDMODEL->lightdata )
	{
		for( i = 0; i < MAX_LIGHTSTYLES; i++ )
			tr.lightstylevalue[i] = 256 * 256;
		return;
	}

	// light animations
	// 'm' is normal light, 'a' is no light, 'z' is double bright
	for( i = 0; i < MAX_LIGHTSTYLES; i++ )
	{
		ls = gEngfuncs.GetLightStyle( i );
		if( !WORLDMODEL->lightdata )
		{
			tr.lightstylevalue[i] = 256 * 256;
			continue;
		}

		if( !gp_cl->paused && frametime <= 0.1f )
			ls->time += frametime; // evaluate local time
@@ -65,18 +65,18 @@ void CL_RunLightStyles( void )

		if( !ls->length )
		{
			tr.lightstylevalue[i] = 256 * scale;
			tr.lightstylevalue[i] = 256;
			continue;
		}
		else if( ls->length == 1 )
		{
			// single length style so don't bother interpolating
			tr.lightstylevalue[i] = ls->map[0] * 22 * scale;
			tr.lightstylevalue[i] = ( ls->pattern[0] - 'a' ) * 22;
			continue;
		}
		else if( !ls->interp || !cl_lightstyle_lerping->flags )
		{
			tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale;
			tr.lightstylevalue[i] = ( ls->pattern[flight%ls->length] - 'a' ) * 22;
			continue;
		}

@@ -89,7 +89,7 @@ void CL_RunLightStyles( void )
		k = ls->map[clight % ls->length];
		l += (float)( k * 22.0f ) * lerpfrac;

		tr.lightstylevalue[i] = (int)l * scale;
		tr.lightstylevalue[i] = (int)l;
	}
}

-- 
2.40.1

[PATCH 14/18] ref: soft: remove unused scale (remnants of r_lightmap_modulate), use integer values for non-interpolated lightstyles Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/soft/r_light.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/ref/soft/r_light.c b/ref/soft/r_light.c
index 6b029cd5..3952e248 100644
--- a/ref/soft/r_light.c
+++ b/ref/soft/r_light.c
@@ -40,23 +40,23 @@ void GAME_EXPORT CL_RunLightStyles( void )
	int		i, k, flight, clight;
	float		l, lerpfrac, backlerp;
	float		frametime = (gp_cl->time -   gp_cl->oldtime);
	float		scale;
	lightstyle_t	*ls;

	if( !WORLDMODEL ) return;
	if( !WORLDMODEL )
		return;

	scale = 1.0f;
	if( !WORLDMODEL->lightdata )
	{
		for( i = 0; i < MAX_LIGHTSTYLES; i++ )
			tr.lightstylevalue[i] = 256 * 256;
		return;
	}

	// light animations
	// 'm' is normal light, 'a' is no light, 'z' is double bright
	for( i = 0; i < MAX_LIGHTSTYLES; i++ )
	{
		ls = gEngfuncs.GetLightStyle( i );
		if( !WORLDMODEL->lightdata )
		{
			tr.lightstylevalue[i] = 256 * 256;
			continue;
		}

		if( !gp_cl->paused && frametime <= 0.1f )
			ls->time += frametime; // evaluate local time
@@ -68,18 +68,18 @@ void GAME_EXPORT CL_RunLightStyles( void )

		if( !ls->length )
		{
			tr.lightstylevalue[i] = 256 * scale;
			tr.lightstylevalue[i] = 256;
			continue;
		}
		else if( ls->length == 1 )
		{
			// single length style so don't bother interpolating
			tr.lightstylevalue[i] = ls->map[0] * 22 * scale;
			tr.lightstylevalue[i] = ( ls->pattern[0] - 'a' ) * 22;
			continue;
		}
		else if( !ls->interp ) // || !CVAR_TO_BOOL( cl_lightstyle_lerping ))
		{
			tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale;
			tr.lightstylevalue[i] = ( ls->pattern[flight%ls->length] - 'a' ) * 22;
			continue;
		}

@@ -92,7 +92,7 @@ void GAME_EXPORT CL_RunLightStyles( void )
		k = ls->map[clight % ls->length];
		l += (float)( k * 22.0f ) * lerpfrac;

		tr.lightstylevalue[i] = (int)l * scale;
		tr.lightstylevalue[i] = (int)l;
	}
}

-- 
2.40.1

[PATCH 15/18] ref: soft: don't depend on light gamma in recursive light point Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/soft/r_light.c  | 22 +++++++---------------
 ref/soft/r_local.h  |  1 -
 ref/soft/r_studio.c |  2 --
 3 files changed, 7 insertions(+), 18 deletions(-)

diff --git a/ref/soft/r_light.c b/ref/soft/r_light.c
index 3952e248..387e3924 100644
--- a/ref/soft/r_light.c
+++ b/ref/soft/r_light.c
@@ -323,18 +323,10 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
		{
			uint	scale = tr.lightstylevalue[surf->styles[map]];

			if( tr.ignore_lightgamma )
			{
				cv->r += lm->r * scale * 2.5; // scale;
				cv->g += lm->g * scale * 2.5; // scale;
				cv->b += lm->b * scale * 2.5; // scale;
			}
			else
			{
				cv->r += gEngfuncs.LightToTexGamma( lm->r ) * scale;
				cv->g += gEngfuncs.LightToTexGamma( lm->g ) * scale;
				cv->b += gEngfuncs.LightToTexGamma( lm->b ) * scale;
			}
			cv->r += lm->r * scale;
			cv->g += lm->g * scale;
			cv->b += lm->b * scale;

			lm += size; // skip to next lightmap

			if( dm != NULL )
@@ -421,9 +413,9 @@ colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot,
			{
				if( lspot ) VectorCopy( g_trace_lightspot, lspot );
				if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
				light.r = Q_min(( cv.r >> 7 ), 255 );
				light.g = Q_min(( cv.g >> 7 ), 255 );
				light.b = Q_min(( cv.b >> 7 ), 255 );
				light.r = Q_min(( cv.r >> 8 ), 255 );
				light.g = Q_min(( cv.g >> 8 ), 255 );
				light.b = Q_min(( cv.b >> 8 ), 255 );
				last_fraction = g_trace_fraction;

				if(( light.r + light.g + light.b ) != 0 )
diff --git a/ref/soft/r_local.h b/ref/soft/r_local.h
index 74ffb6b4..2c8e1b34 100644
--- a/ref/soft/r_local.h
+++ b/ref/soft/r_local.h
@@ -270,7 +270,6 @@ typedef struct
	int		realframecount;	// not including viewpasses
	int		framecount;

	qboolean		ignore_lightgamma;
	qboolean		fCustomRendering;
	qboolean		fResetVis;
	qboolean		fFlipViewModel;
diff --git a/ref/soft/r_studio.c b/ref/soft/r_studio.c
index 92bc4b6c..77e7b36e 100644
--- a/ref/soft/r_studio.c
+++ b/ref/soft/r_studio.c
@@ -3412,9 +3412,7 @@ void R_GatherPlayerLight( void )
	cl_entity_t	*view = tr.viewent;
	colorVec		c;

	tr.ignore_lightgamma = true;
	c = R_LightPoint( view->origin );
	tr.ignore_lightgamma = false;
	gEngfuncs.SetLocalLightLevel( ( c.r + c.g + c.b ) / 3 );
}

-- 
2.40.1

[PATCH 16/18] ref: soft: adapt studio renderer to new gamma implementation Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/soft/r_studio.c | 66 ++++++++++++++++++++++++++++-----------------
 1 file changed, 41 insertions(+), 25 deletions(-)

diff --git a/ref/soft/r_studio.c b/ref/soft/r_studio.c
index 77e7b36e..3a9670e7 100644
--- a/ref/soft/r_studio.c
+++ b/ref/soft/r_studio.c
@@ -107,7 +107,7 @@ typedef struct
	int		numlocallights;
	int		lightage[MAXSTUDIOBONES];
	dlight_t		*locallight[MAX_LOCALLIGHTS];
	color24		locallightcolor[MAX_LOCALLIGHTS];
	uint		locallightcolor[MAX_LOCALLIGHTS][3];
	vec4_t		lightpos[MAXSTUDIOVERTS][MAX_LOCALLIGHTS];
	vec3_t		lightbonepos[MAXSTUDIOBONES][MAX_LOCALLIGHTS];
	float		locallightR2[MAX_LOCALLIGHTS];
@@ -1377,13 +1377,13 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )
		{
			VectorSet( lightDir, mv->skyvec_x, mv->skyvec_y, mv->skyvec_z );

			light.r = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_r, 255 ));
			light.g = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_g, 255 ));
			light.b = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_b, 255 ));
			light.r = mv->skycolor_r;
			light.g = mv->skycolor_g;
			light.b = mv->skycolor_b;
		}
	}

	if(( light.r + light.g + light.b ) < 16 ) // TESTTEST
	if(( light.r + light.g + light.b ) == 0 )
	{
		colorVec	gcolor;
		float	grad[4];
@@ -1431,6 +1431,13 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )
		}
	}

	if( ent->curstate.renderfx == kRenderFxLightMultiplier && ent->curstate.iuser4 != 10 )
	{
		light.r *= ent->curstate.iuser4 / 10.0f;
		light.g *= ent->curstate.iuser4 / 10.0f;
		light.b *= ent->curstate.iuser4 / 10.0f;
	}

	VectorSet( finalLight, light.r, light.g, light.b );
	ent->cvFloorColor = light;

@@ -1462,15 +1469,15 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )

			VectorAdd( lightDir, dist, lightDir );

			finalLight[0] += gEngfuncs.LightToTexGamma( dl->color.r ) * ( add / 256.0f ) * 2.0f;
			finalLight[1] += gEngfuncs.LightToTexGamma( dl->color.g ) * ( add / 256.0f ) * 2.0f;
			finalLight[2] += gEngfuncs.LightToTexGamma( dl->color.b ) * ( add / 256.0f ) * 2.0f;
			finalLight[0] += dl->color.r * ( add / 256.0f );
			finalLight[1] += dl->color.g * ( add / 256.0f );
			finalLight[2] += dl->color.b * ( add / 256.0f );
		}
	}

	if( FBitSet( ent->model->flags, STUDIO_AMBIENT_LIGHT ))
		add = 0.6f;
	else add = 0.9f;
	else add = bound( 0.75f, v_direct->value, 1.0f );

	VectorScale( lightDir, add, lightDir );

@@ -1564,9 +1571,9 @@ void R_StudioEntityLight( alight_t *lightinfo )

			if( k != -1 )
			{
				g_studio.locallightcolor[k].r = gEngfuncs.LightToTexGamma( el->color.r );
				g_studio.locallightcolor[k].g = gEngfuncs.LightToTexGamma( el->color.g );
				g_studio.locallightcolor[k].b = gEngfuncs.LightToTexGamma( el->color.b );
				g_studio.locallightcolor[k][0] = gEngfuncs.LinearGammaTable( el->color.r << 2 );
				g_studio.locallightcolor[k][1] = gEngfuncs.LinearGammaTable( el->color.g << 2 );
				g_studio.locallightcolor[k][2] = gEngfuncs.LinearGammaTable( el->color.b << 2 );
				g_studio.locallightR2[k] = r2;
				g_studio.locallight[k] = el;
				lstrength[k] = minstrength;
@@ -1642,7 +1649,7 @@ void R_StudioLighting( float *lv, int bone, int flags, vec3_t normal )

		r = SHADE_LAMBERT;

 		// do modified hemispherical lighting
		// do modified hemispherical lighting
		if( r <= 1.0f )
		{
			r += 1.0f;
@@ -1661,7 +1668,8 @@ void R_StudioLighting( float *lv, int bone, int flags, vec3_t normal )
	}

	illum = Q_min( illum, 255.0f );
	*lv = illum * (1.0f / 255.0f);

	*lv = gEngfuncs.LightToTexGammaEx( illum * 4 ) / 1023.0f;
}

/*
@@ -1681,11 +1689,11 @@ static void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], const vec3_t normal,
		return;
	}

	VectorCopy( color, finalLight );
	VectorSet( finalLight, 0, 0, 0 );

	for( i = 0; i < g_studio.numlocallights; i++ )
	{
		float r;
		float	r;

		r = DotProduct( normal, light[i] );
		if( likely( !tr.fFlipViewModel ))
@@ -1705,21 +1713,29 @@ static void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], const vec3_t normal,
				else light[i][3] = 0.0001f;
			}

			temp = Q_min( r * light[i][3] / 255.0f, 1.0f );

			localLight[0] = (float)g_studio.locallightcolor[i].r * temp;
			localLight[1] = (float)g_studio.locallightcolor[i].g * temp;
			localLight[2] = (float)g_studio.locallightcolor[i].b * temp;
			temp = r * light[i][3];

			VectorAddScalar( g_studio.locallightcolor[i], temp, localLight );
			VectorAdd( finalLight, localLight, finalLight );
		}
	}

	VectorScale( finalLight, 255.0f, finalLight );
	if( !VectorIsNull( finalLight ))
	{
		for( i = 0; i < 3; i++ )
		{
			float c = finalLight[i] + gEngfuncs.LinearGammaTable( color[i] * 1023.0f );

	out[0] = Q_min( (int)( finalLight[0] ), 255 );
	out[1] = Q_min( (int)( finalLight[1] ), 255 );
	out[2] = Q_min( (int)( finalLight[2] ), 255 );
			if( c > 1023.0f )
				out[i] = 255;
			else
				out[i] = gEngfuncs.ScreenGammaTable( c ) >> 2;
		}
	}
	else
	{
		VectorScale( color, 255.0f, out );
	}
}

static void R_StudioSetColorBegin(short *ptricmds, vec3_t *pstudionorms )
-- 
2.40.1

[PATCH 17/18] ref: soft: reorder applying light gamma Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/soft/r_surf.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/ref/soft/r_surf.c b/ref/soft/r_surf.c
index 3debf716..a2785e21 100644
--- a/ref/soft/r_surf.c
+++ b/ref/soft/r_surf.c
@@ -211,13 +211,9 @@ static void R_BuildLightMap( void )

		for( i = 0, bl = blocklights; i < size; i++, bl += 1, lm++ )
		{
			bl[0] += gEngfuncs.LightToTexGamma( lm->r ) * scale;
			bl[0] += gEngfuncs.LightToTexGamma( lm->g ) * scale;
			bl[0] += gEngfuncs.LightToTexGamma( lm->b ) * scale;

			//printf("test\n");
			//bl[1] += gEngfuncs.LightToTexGamma( lm->g ) * scale;
			//bl[2] += gEngfuncs.LightToTexGamma( lm->b ) * scale;
			bl[0] += lm->r * scale;
			bl[1] += lm->g * scale;
			bl[2] += lm->b * scale;
		}
	}

@@ -245,7 +241,10 @@ static void R_BuildLightMap( void )
	// bound, invert, and shift
		for (i=0 ; i<size ; i++)
		{
			t = (int)blocklights[i];
			if( blocklights[i] < 65280 )
				t = gEngfuncs.LightToTexGammaEx( blocklights[i] >> 6 ) << 6;
			else t = (int)blocklights[i];

			if (t < 0)
				t = 0;
			if( t > 65535 * 3 )
-- 
2.40.1

[PATCH 18/18] ref: gl: particles aren't supposed to care about gamma Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 ref/gl/gl_rpart.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/ref/gl/gl_rpart.c b/ref/gl/gl_rpart.c
index c2c71845..0a14db78 100644
--- a/ref/gl/gl_rpart.c
+++ b/ref/gl/gl_rpart.c
@@ -91,9 +91,7 @@ void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float
			if( alpha > 255 || p->type == pt_static )
				alpha = 255;

			pglColor4ub( gEngfuncs.LightToTexGamma( color.r ),
				gEngfuncs.LightToTexGamma( color.g ),
				gEngfuncs.LightToTexGamma( color.b ), alpha );
			pglColor4ub( color.r, color.g, color.b, alpha );

			pglTexCoord2f( 0.0f, 1.0f );
			pglVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] );
-- 
2.40.1

[PATCH 19/19] engine: dedicated: add TextureToGamma stub for imagelib Export this patch

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
---
 engine/common/dedicated.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/engine/common/dedicated.c b/engine/common/dedicated.c
index 9b7d56dd..d9be5944 100644
--- a/engine/common/dedicated.c
+++ b/engine/common/dedicated.c
@@ -247,4 +247,9 @@ void CL_HudMessage( const char *pMessage )

}

byte TextureToGamma( byte b )
{
	return b;
}

#endif // XASH_DEDICATED
-- 
2.40.1