Gamma Correction

Started by
4 comments, last by matt77hias 6 years, 6 months ago

If a material is represented by a base color and some material parameters which are all normalized in the range [0,1], one typically only needs to apply inverse gamma correction on the base color?

Similarly if one uses both a coefficient and texture, which are multiplied, one typically only needs to apply inverse gamma correction to the product of the base color coefficient and texture?

Does one normally perform this inverse gamma correction while packing the GBuffer or while unpacking the GBuffer (with regard to the base color texture of the GBuffer)?

Should one use a sRGB format to avoid having to manually apply the inverse gamma correction?

🧙

Advertisement
1 hour ago, matt77hias said:

If a material is represented by a base color and some material parameters which are all normalized in the range [0,1], one typically only needs to apply inverse gamma correction on the base color?

"Gamma correction" refers to both the encoding and decoding step. To be clear, I find it best to refer to the Linear->sRGB step and the sRGB->Linear step.

Typically anything that's authored by eye requires a sRGB->Linear conversion. This is because the artist who created the data was viewing it on an sRGB monitor. So when they looked at 187/255 on their monitor, they saw a value that appeared to them to be about 50% as bright as 255/255, meaning they're directly painting in sRGB format. Moreover, anything that represents a colour that will be viewed by humans benefits from great compression in sRGB format. When storing linear RGB you need more than 10 bits per channel to not perceive any colour banding, while sRGB achieves this with only 8 bits per channel.

So yes - base colour needs a sRGB->Linear conversion before doing your lighting calculations.

Normal maps definitely do not -- the source data is linear (127 is in the middle), so attempting to decode it when it's not encoded will just bias the normals off to the side :P

Alpha masks, metalness masks, roughness values, probably don't need it... but you can try it to see if artists like the "incorrect" bias. e.g. in some PBR papers you'll see that they choose to expose roughness-squared to their artists instead of roughness, simply because the artists liked that parameter better.

9 minutes ago, Hodgman said:

Moreover, anything that represents a colour that will be viewed by humans benefits from great compression in sRGB format.

So in that case the sRGB->linear is done by the hardware and only the coefficient needs to be manually converted. Is the latter normally done on the CPU or shader code?

One thing I do not understand about gamma correction is the portability? If someone uses an old mac with gamma=1.8, how is someone else with a gamma=2.2 able to see what is intended?

🧙

3 minutes ago, matt77hias said:

So in that case the sRGB->linear is done by the hardware

If you use one of the blah_SRGB texture formats, then yeah, the hardware will to sRGB->Linear when you read from them, and also do Linear->sRGB when you write to them.

So if you've got sRGB texture maps on your objects, and are copying them into an sRGB GBuffer, the hardware will do [SourceTexture]-sRGB->Linear-[Pixel shader]-Linear->sRGB-[GBuffer]... This seems wasteful, but there's transistors in the HW dedicated to the tasks, so I don't think it's actually that harmful.

3 minutes ago, matt77hias said:

the coefficient needs to be manually converted. Is the latter normally done on the CPU or shader code?

I'm not sure what coefficient you mean?

Any per-material parameters that you're going to put into a cbuffer, but are source from an artist's colour picker -- yeah, you can do sRGB->Linear conversion on the CPU before you place the value into the cbuffer.

4 minutes ago, matt77hias said:

One thing I do not understand about gamma correction is the portability? If someone uses an old mac with gamma=1.8, how is someone else with a gamma=2.2 able to see what is intended?

So, the source data you control. You buy all of your artists an sRGB monitor and use a colour calibrator to ensure that they're all fairly well calibrated. Then you know that your source data is sRGB. Internally you store sRGB data in your GBuffer, because there's magic HW support for it, and your source data is sRGB (so storing linear data in your GBuffer would either be lossy, or require a 16bit channel format...).

For final output (the swap chain), you can create this as a *_SRGB texture and get automatic conversion from linear->sRGB when writing to it... but yeah, this assumes that the user actually has an sRGB / gamma 2.2 monitor.

If you want to give your users a "gamma" slider, which allows them to see the image as you intended, even though they've got a silly gamma 1.8 or gamma 2.4 monitor, then you've got to do a bit of work :) Instead of making the swapchain with an *_SRGB, make a non-SRGB swap chain. This disables the automatic linear->sRGB conversion when writing data into it. Instead, in all of your shaders that directly write into the swap-chain, implement gamma encoding yourself in the shader code -- e.g. return pow( result, rcp_outputGamma )

37 minutes ago, Hodgman said:

If you want to give your users a "gamma" slider, which allows them to see the image as you intended, even though they've got a silly gamma 1.8 or gamma 2.4 monitor, then you've got to do a bit of work :) Instead of making the swapchain with an *_SRGB, make a non-SRGB swap chain. This disables the automatic linear->sRGB conversion when writing data into it. Instead, in all of your shaders that directly write into the swap-chain, implement gamma encoding yourself in the shader code -- e.g. return pow( result, rcp_outputGamma )

Is this the same slider as "move the slider till the image is barely visible", I have seen in some games?

Is it common feature (seem to have a large impact on the design)?

37 minutes ago, Hodgman said:

I'm not sure what coefficient you mean?

I use a coefficient and texture for all my material parameters. If you do not want to vary the parameter between surface positions, just use a white texture and modify the coefficient. Otherwise you need to create lots of single texel textures. (I now also notice that I need two textures if I want to use sRGB textures for colors and RGB textures for the remainder. Except for black and white because they just map to the same values in both spaces.)

🧙

This topic is closed to new replies.

Advertisement