GL Gamma Correction

Discuss programming topics for the various GPL'd game engine sources.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: GL Gamma Correction

Post by Spike »

gl_brightness and gl_contrast are supposed to exist in fte, but whether they're identical to the gamma+contrast cvars is a different matter. If it ain't exact, it ain't gamma. :s
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: GL Gamma Correction

Post by Baker »

reckless wrote:Hmm an interresting non shader based gamma function i have from one of mh's older engines.

Code: Select all

/*
===================
SCR_SetBrightness

Enables setting of brightness without having to do any mondo fancy shite.
It's assumed that we're in the 2D view for this...

Basically, what it does is multiply framebuffer colours by an incoming constant between 0 and 2
===================
*/
void SCR_SetBrightness (float brightfactor)
{
    // divide by 2 cos the blendfunc will sum src and dst
    const GLfloat brightblendcolour[4] = {0, 0, 0, 0.5f * brightfactor};
    const GLfloat constantwhite[4] = {1, 1, 1, 1};

    // don't trust == with floats, don;t bother if it's 1 cos it does nothing to the end result!!!
    if (brightfactor > 0.99 && brightfactor < 1.01)
    {
        return;
    }

    glColor4fv (constantwhite);
    glEnable (GL_BLEND);
    glDisable (GL_ALPHA_TEST);
    glBlendFunc (GL_DST_COLOR, GL_SRC_COLOR);

    // combine hack...
    // this is weird cos it uses a texture but actually doesn't - the parameters of the
    // combiner function only use the incoming fragment colour and a constant colour...
    // you could actually bind any texture you care to mention and get the very same result...
    // i've decided not to bind any at all...
    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT);
    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, brightblendcolour);

    glBegin (GL_QUADS);

    glTexCoord2f (0, 0);
    glVertex2f (0, 0);

    glTexCoord2f (0, 1);
    glVertex2f (0, GL_State.OrthoHeight);

    glTexCoord2f (1, 1);
    glVertex2f (GL_State.OrthoWidth, GL_State.OrthoHeight);

    glTexCoord2f (1, 0);
    glVertex2f (GL_State.OrthoWidth, 0);

    glEnd ();

    // restore combiner function colour to white so as not to mess up texture state
    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constantwhite);

    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glDisable (GL_BLEND);
    glEnable (GL_ALPHA_TEST);
    glColor4fv (constantwhite);
}
uses opengl's combine extention so will not Work for the software client.
Reckless, I don't think that does real gamma. But if It really does real gamma, feel free to smack me upside the head and point out how it does.

To me that looks similar to the "draw a brightness poly over the whole 2D surface" method.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: GL Gamma Correction

Post by revelator »

Indeed what it does is a bit like doing overbright but it emulates gamma amazingly well though ;)
Also easy to use as it uses the v_gamma cvar directly.
Productivity is a state of mind.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: GL Gamma Correction

Post by jitspoe »

Barnes wrote:ahh yes!!!
photoshop math on glsl and hlsl (im use some things)
http://mouaif.wordpress.com/2009/01/05/ ... l-shaders/
Hey, my coworker wrote those! Small world. :)



As for the GL_COMBINE stuff, that effectively just multiplies the output. It's actually pretty useful when blending lightmaps with textures, as it's effectively a "free" way to brighten things up. I use this in Paintball2 (gl_overbright is the cvar to enable/disable it). If that's not bright enough, I've also got the method posted above, where it draws a quad over the whole screen to brighten it (gl_brightness cvar). Downside to that is it's a pretty big fillrate hit, since it has to make another pass over the whole screen. I'm not sure if that's more or less expensive than a shader (I would imagine less), but it will be compatible with more video cards. It does not, however, behave like gamma. It just scales the brightness of everything up.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: GL Gamma Correction

Post by Spike »

GL_RGB_SCALE does scale the output, yes (overbrights etc). Activate it when drawing everything else and you can double the contrast of the screen, but you have to be really careful with blend modes.
contrast is easy to implement - just double the colour values.
brightness is also easy - just add to the colour values.
actual gamma requires exponents, however. luckily, it should be possible to just multiply the values enough times. the down side is that doing that will loose precision. a lot of precision.
Barnes
Posts: 232
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow
Contact:

Re: GL Gamma Correction

Post by Barnes »

jitspoe wrote:
Barnes wrote:ahh yes!!!
photoshop math on glsl and hlsl (im use some things)
http://mouaif.wordpress.com/2009/01/05/ ... l-shaders/
Hey, my coworker wrote those! Small world. :)
Damn! Real small world! Image
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: GL Gamma Correction

Post by revelator »

Aye its not true gamma :) but if someone can use it for whatever its easy to implement call the function from the same place as the old gamma and give it a cvar as argument for the bright factor.
Small note it uses negative values so if you want to use it with the standard quake menu you have to invert the menu scales. Maybe nice for a scalable overbright setting hmm :) ?.
Productivity is a state of mind.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: GL Gamma Correction

Post by Baker »

reckless wrote:Aye its not true gamma :) but if someone can use it for whatever its easy to implement call the function from the same place as the old gamma and give it a cvar as argument for the bright factor.
Small note it uses negative values so if you want to use it with the standard quake menu you have to invert the menu scales. Maybe nice for a scalable overbright setting hmm :) ?.
Shockingly enough, I'm only getting a 4 FPS hit off this and it works pretty well.

Now I'm trying to debate what to do. Damn you reckless! :D
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: GL Gamma Correction

Post by Baker »

Sat on fence then went with this.

Reasons:
1. Loss of 4 fps 223 fps to 219 fps on my $300 windows laptop (this $300 laptop is incredible ... it's terrific and I'm picky)
2. No need for gamma and contrast. Just brightness. Winner.
3. No more platform specific hardware gamma code.
4. Screenshots don't need gamma correction applied (not that I did that). Neither does video capture.
5. Affects only the Window itself.

Drawbacks:
1. Slightly narrower capabilities of brightening the screen. Hardware gamma has more brightening power.
2. Slight loss of FPS and fps matters (within reason). But 1%-2% loss is nothing.

I had rewritten all the Windows hardware gamma code really nice and orderly. And now I'm throwing it away. A bit ironic, but I'll take this total solution over hardware gamma every day.

Since "gamma" is a standard Quake cvar (some mods even use it for brightness effects like flash grenades ... although they shouldn't have used the cvar) I internally call it scr_brightness but keeps same external cvar name.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: GL Gamma Correction

Post by revelator »

Happy that it found a use :) fps hit is as you say minimal and it Works rather well so i thought someone might find it interresting even though its not real gamma ;).
Heh funny i use the same cvar name small World indeed.
Productivity is a state of mind.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: GL Gamma Correction

Post by jitspoe »

In a lot of cases, we don't actually want gamma - we just want things brighter, so it's ideal for that. If things are simply too dark, using gamma to brighten them can result in washed-out visuals (loss of contrast and saturation). If you want brightness in the standard case, you can use this when combining the lightmap and textures to avoid the 4fps hit, though it would require modifying a lot more code.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: GL Gamma Correction

Post by Baker »

Burial ... Hardware gamma code: I can't imagine ever using it again and am removing it, but some of it I touched up sensibly.

Code: Select all

void VID_Local_Gamma_Reset (void)
{
	int i;
	HDC hdc = GetDC (NULL);
	WORD gammaramps[3][256];

	for (i = 0;i < 256;i++)
		gammaramps[0][i] = gammaramps[1][i] = gammaramps[2][i] = (i * 65535) / 255;

	i = SetDeviceGammaRamp(hdc, &gammaramps[0][0]);
	ReleaseDC (NULL, hdc);
}


/*
================
VID_Gamma_SetGamma -- apply gamma correction
================
*/
void VID_Local_Gamma_SetGamma (void)
{
	if (wplat.draw_context && vid.gammaworks)
	{
		if (SetDeviceGammaRamp(wplat.draw_context, vid.gammaramp) == false)
			Con_Printf ("VID_Gamma_SetGamma: failed on SetDeviceGammaRamp\n");
	}
}

/*
qboolean VID_Local_Validate_Gamma (void)
{
		static unsigned short checktable[768];
		Con_Printf ("Gamma guardian: ");
		if (GetDeviceGammaRamp (wplat.draw_context, checktable))
		{
			if (memcmp(&checktable, &vid.gammaramp, sizeof(checktable)) !=0 )
				Con_Printf ("Gamma is wrong!\n");
			else Con_Printf ("Gamma is correct!\n");
		} else Con_Printf ("Couldn't get gamma table\n");
} */

/*
================
VID_Gamma_Restore -- restore system gamma
================
*/
void VID_Local_Gamma_Restore (void)
{
	if (wplat.draw_context && vid.gammaworks)
	{
		if (SetDeviceGammaRamp(wplat.draw_context, vid.systemgammaramp) == false)
			Con_Printf ("VID_Gamma_Restore: failed on SetDeviceGammaRamp\n");
	}
}


/*
================
VID_Gamma_f -- callback when the cvar changes
================
*/
void VID_Local_Gamma_f (cvar_t *var)
{
	int i;

	if (vid_gamma.default_string == NULL || vid_gamma.default_string == NULL)
		return; // Presumed to be in initialization

 	for (i=0; i<256; i++)
	{
		float inf = (255 * pow ((i + 0.5) / 255.5, vid_gamma.value) + 0.5);

		inf -= 128;
		inf *= vid_contrast.value;
		inf += 128;
		vid.gammaramp[i +   0] =
		vid.gammaramp[i + 256] =
		vid.gammaramp[i + 512] = CLAMP (0, (int) inf, 255) << 8;
	}
	VID_Gamma_SetGamma ();
}

qboolean VID_Local_Gamma_Init (void)
{
	HDC hdc = GetDC (NULL);
	if (GetDeviceGammaRamp (hdc, vid.systemgammaramp))
		return true;
	return false;
}
And

Code: Select all

cvar_t		vid_gamma = {"gamma", "1", CVAR_ARCHIVE}; //johnfitz -- moved here from view.c
cvar_t		vid_contrast = {"contrast", "1", CVAR_ARCHIVE};

void VID_Gamma_Think (void)
{
	if (vid.ActiveApp && !vid.Minimized && vid.gammaworks /*&& wplat.draw_context*/)
	{
		if (vid.gamma_checktime && realtime > vid.gamma_checktime)
		{
			VID_Gamma_Restore ();
			VID_Gamma_SetGamma ();
			vid.gamma_checktime = 0;
			Con_DPrintf ("Gamma restore\n");
		}
	}
}

void VID_Gamma_Shutdown (void)
{
	VID_Local_Gamma_Restore ();
}

void VID_Gamma_Init (void)
{
	if ( (vid.gammaworks = VID_Local_Gamma_Init ()) == false)
		Con_Warning ("Hardware gamma not available.\n");

	Cvar_RegisterVariableWithCallback (&vid_contrast, VID_Local_Gamma_f);
	Cvar_RegisterVariableWithCallback (&vid_gamma, VID_Local_Gamma_f);
}

void VID_Gamma_SetGamma (void)
{
	VID_Local_Gamma_SetGamma ();
}

void VID_Gamma_Restore (void)
{
	VID_Local_Gamma_Restore ();
}
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Barnes
Posts: 232
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow
Contact:

Re: GL Gamma Correction

Post by Barnes »

Kill'em, kill'em!!!!
Seriously I have already killed the hardware gamma ramps. A terrible thing has been :D
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: GL Gamma Correction

Post by revelator »

Definatly worth it sifting through mh's older OpenGL engine sources, lots of non standard but amazingly well working ideas :) His Q2 sources are also worth having a look at, many nice ideas in them.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: GL Gamma Correction

Post by revelator »

Btw try replacing tenebraes old gamma code with the code posted :) i think your going to like it.
Productivity is a state of mind.
Post Reply