Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

When using a gamma-correct pipeline, you have to work with floating-point rendertargets. Otherwise, you will get severe banding due to the insufficient precision of the usual 8-bit-per-channel integer rendertargets.

Is there any way around this? Any good way to implement gamma-correct rendering without using floating-point rendertargets?

This is on desktop PCs using Windows and DirectX.

share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

You can keep your buffers in sRGB and convert from gamma to linear in the shader when reading a texture, and back to gamma on output. Newer GPUs even have hardware support for doing these conversions automatically. In Direct3D 10/11 you can activate this by setting up your textures and render targets with sRGB formats. It also works with blending (blending will be done in linear space).

Older (Direct3D 9) GPUs may also support gamma conversions on read and write, but still do blending in linear space, which limits the usefulness of this approach, since e.g. additive blending for accumulating light will not be correct.

Beyond that, if 8-bit sRGB isn't enough precision for you (e.g. you're doing math that introduces banding even in 8-bit sRGB, or you want to do HDR) then floating-point render targets are probably the best way.

Some GPUs/platforms support integer render targets with more than 8 bits per channel. For example, there is an R10G10B10A2 format seen sometimes. However, 10 bits still probably aren't enough to avoid the banding. This article calculates that the a minimum linear-space precision of 12 bits is needed to match 8 bits of sRGB. Some GPUs even have a 16-bit integer render target format, but I don't think this is widely supported, and I'm not sure if you can do blending, bilinear filtering, etc. with these render targets.

It's also possible to use 8-bit framebuffers with the alpha channel used to improve precision, as in LogLUV or RGBM. But again, blending does not work with such encodings. Alpha compositing may work acceptably, but additive blending does not, so accumulating lights in such formats is challenging. You have to avoid using hardware blending and write shaders that decode, update, and re-encode the format.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.