Gamma Correction
|
Sections
|
|
|
CRT Behavior Gamma Correction Gamma Ramp APIs References and Links
|
|
|
CRT Behavior
|
|
|
The values in your frame buffer (typically 8-bits per component) and the resulting cathode-ray tube (CRT) intensity have a nonlinear relationship. This is due to the fact that the intensity of pixels on a CRT is a nonlinear function of the voltage input. Uncorrected, the voltage input to the CRT is a linear function of the values in the frame buffer.
This non-linear relationship can be approximated by the following function:
I = Eg
|
|
|
where
- E is the code in the frame buffer (or voltage of the electron gun in the CRT)
- g is the gamma of the display
- I is the resulting lighting intensity
A graph for three different g's is shown below:
|
|
|

|
|
|
The result of this nonlinear relationship is poor use of the precision of the frame buffer. For example, on the left end of the curve, a large number of possible frame buffer values map to a small number of possible intensities. Conversely, very few frame buffer color values are available to represent high intensity pixels. This can result in very dark, poor quality real-time environments as well as banding at high intensity.
|
|
|
Gamma Correction
|
|
|
To counteract the nonlinear response of the monitor, graphics accelerators provide a mechanism called "gamma correction." The graphics accelerator has a digital to analog convertor (DAC) which is constantly scanning the frame buffer and sending the results to the monitor. This happens at the monitor refresh rate and is independent of the frame rate of any given application.
As these frame buffer values are scanning out through the DAC, they are run through a programmable table in the DAC to gamma correct them. This table represents another function which, when followed by the non-linear response of the monitor, causes a near linear mapping from frame buffer values to screen intensities. Tuning this gamma table for your application is a part of the art of real-time 3D application development.
|
|
|
Gamma Table APIs
|
|
|
Windows® - SetDeviceGammaRamp()
In Win32, there are two entrypoints for setting the gamma table. These entrypoints give the application control over how much (if any) gamma correction is performed. Special effects like screen flashes can even be done inexpensively by using the gamma table to briefly invert frame buffer values during scan out.
The most generic API for setting the gamma table is the Win32 entrypoint SetDeviceGammaRamp(). Since this is just part of Win32, any application can set it, though it's really only appropriate for fullscreen applications to take control of the gamma table, as there is currently no notion of per-window gamma in the OS. This entrypoint is what OpenGL® applications typically use to set their gamma ramps. The function prototype looks like:
|
BOOL WINAPI SetDeviceGammaRamp( HDC hDC, LPVOID lpRamp );
|
- where
-
- hDC is a handle to the device context
- lpRamp is a pointer to a buffer containing the
gamma ramp to be set. The gamma ramp is specified
in three consecutive arrays (for r, g and b) of
256 WORDs each, which contain the mapping between
RGB values in the frame buffer and DAC values.
The RGB values must be stored in the most significant
bits of each WORD to increase DAC independence.
- The function returns TRUE on success and FALSE
on failure.
Also, see the MSDN documentation.
|
|
|
Windows® - IDirect3DDeviceX::SetGammaRamp()
|
|
|
Direct3D® applications can use the IDirect3DDeviceX::SetGammaRamp() entrypoint to program the current device's gamma table. Though the syntax is slightly different, the effect of this entrypoint is the same as Win32's SetDeviceGammaRamp().
Also, see the MSDN documentation.
|
|
|
Radeon® Support
|
|
|
From the RAGE 128 PRO™ onward, ATI chips have supported 8.2 fixed-point gamma table entries, which is higher precision than their predecessors (8.0). By providing meaningful 8.8 fixed-point data to the API entrypoint(s) above, you take advantage of this added precision.
|
|
|
- Links
-
|
|
|
|
|
|