Gamma Correction in OpenGL

Started by
9 comments, last by dpadam450 13 years, 2 months ago
Hi everyone. I'm just wondering how I might be able to achieve gamma correction in a fullscreen OpenGL application ? I have an app up and running right now which seems to be very dark on some monitors and much brighter on others and I would like to add in the option to be able to change this. I presume I'll need somehow to get access to some color tables for R,G,B and change those in a non-linear way to account for the darkness of the monitor. I can't seem to find any good resources about this on the net so any help or advice you could would be great. Cheers! Darragh
Advertisement
There is some function to do it. Though straight to gpu.
...
Google got me this, I'm lucky

http://msdn2.microsoft.com/en-us/library/ms970748.aspx

long(ish) information with some good examples and code
------Randomness to the end O.o
Quote:Original post by Inestical
There is some function to do it. Though straight to gpu.
...
Google got me this, I'm lucky

http://msdn2.microsoft.com/en-us/library/ms970748.aspx

long(ish) information with some good examples and code


Thanks for the reply Inestical. Yeah i recall seeing that article before in my search, problem is though it only seems to deal with indexed mode and not 32-bit color which is what I am using at the moment- sorry for not mentioning this earlier. Is there any way I can apply this to 32-bit color mode ?
Anyone ? There must be some way to do this, has anyone attempted gamma correction in true color mode before ?
there is some functions for that, mostly I would figure it out to be.. yeah.

Add additional 'gammastep' as glColor4f(0.2, 0.2, 0.2, 1.0); or so.
------Randomness to the end O.o

Gamma correction is actually not within the scope of OpenGL. I think there is some extension "I3D_gamma" if I'm not mistaking. But I never encountered any driver actually supporting it.
On MS Windows you can do gamma correction on the entire display. This works fine for fullscreen applications. For a windowed app it is less suitable unless you don't mind changing gamma for the surrounding desktop also.
Here is a small code sample. Note that the Device Context of the screen is obtained by passing "NULL": to GetDC.

// p_Gamma = [-1.0 , 1.0]
void CorrectGamma(float p_Gamma)
{
HDC l_DisplayHDC = GetDC(NULL);

if (l_DisplayHDC != NULL)
{
WORD l_GammaRamp[3][256];

for (size_t l_Index = 0; l_Index < 256; l_Index++)
{
int l_Value = (int)l_Index*(int((p_Gamma*0.5f+0.5f)*255)+128);
l_Value = l_Value > 65535 ? 65535 : l_Value;

l_GammaRamp[0][l_Index] =
l_GammaRamp[1][l_Index] =
l_GammaRamp[2][l_Index] = (WORD)l_Value;
}

if (SetDeviceGammaRamp(l_DisplayHDC, l_GammaRamp) == TRUE)
{
m_Gamma = p_Gamma; // Store gama setting
}

ReleaseDC(NULL, l_DisplayHDC);
}


---------------------------------
Interrested in planetary terrain rendering?
Take a look at ovPlanet:
www.OrganicVectory.com
Thanks Treesong! Thats perfect- exactly what I was looking for. Will give this a try tonight.

Best regards,
Darragh.
There are functions that allow you to specify a lut for GL to use. Not sure how well-supported they are, but they're in the docs somewhere.

A

Gamma correction is actually not within the scope of OpenGL. I think there is some extension "I3D_gamma" if I'm not mistaking. But I never encountered any driver actually supporting it.
On MS Windows you can do gamma correction on the entire display. This works fine for fullscreen applications. For a windowed app it is less suitable unless you don't mind changing gamma for the surrounding desktop also.
Here is a small code sample. Note that the Device Context of the screen is obtained by passing "NULL": to GetDC.

// p_Gamma = [-1.0 , 1.0]
void CorrectGamma(float p_Gamma)
{
HDC l_DisplayHDC = GetDC(NULL);

if (l_DisplayHDC != NULL)
{
WORD l_GammaRamp[3][256];

for (size_t l_Index = 0; l_Index < 256; l_Index++)
{
int l_Value = (int)l_Index*(int((p_Gamma*0.5f+0.5f)*255)+128);
l_Value = l_Value > 65535 ? 65535 : l_Value;

l_GammaRamp[0][l_Index] =
l_GammaRamp[1][l_Index] =
l_GammaRamp[2][l_Index] = (WORD)l_Value;
}

if (SetDeviceGammaRamp(l_DisplayHDC, l_GammaRamp) == TRUE)
{
m_Gamma = p_Gamma; // Store gama setting
}

ReleaseDC(NULL, l_DisplayHDC);
}


---------------------------------
Interrested in planetary terrain rendering?
Take a look at ovPlanet:
www.OrganicVectory.com



I just want to know how to get it to make only the application's gamma is manipulated?

I just want to know how to get it to make only the application's gamma is manipulated?
[/quote]

Have you considered rendering to an off-screen framebuffer? Have a look for tutorials relating to "render to texture". Then you can think of rendering as taking a picture, and you can use any shader you like when transferring that rendered picture to your window. Any GPU that supports OpenGL 2.0 should be fine with this.

When the application starts, you create an FBO (framebuffer object) with the same resolution as the window. I'd recommend GL_RGBA16F for its internal format, as it has enough accuracy to withstand a wide variety of colour-corrections, and its high dynamic range allows a wide variety of interesting special effects.

For each frame, you'd render everything* into the FBO, instead of into the window.

Finally, you'd bind a gamma-correction fragment shader, and using that FBO as a texture, render a window-filling quad. Voila: gamma-corrected OpenGL. You could easily add brightness/contrast, white-balance & exposure controls, too.



*except for the gamma controls themselves. You'd probably want to draw them last, straight into the window, so they can't be accidentally made invisible.

This topic is closed to new replies.

Advertisement