When I output a color via fragColor
in the main()
function of a fragment shader, are the color component intensities interpreted as linear RGB or sRGB? Or to put it differently, do I have to perform gamma correction in my shader or is this already being taken care of?
If there is no general answer but depends on some OpenGL property: How do I set this property?
To avoid misunderstanding: The respective color has been entirely programmatically generated, there are no textures or the like (which may necessitate input gamma correction).
Every fragment shader output is routed to a specific image in the framebuffer (based on glDrawBuffers
state). That image has a format. That format defines the default colorspace interpretation of the corresponding output.
Therefore, if you are writing a value to an image in a linear RGB format, then the system will interpret that value as a linear RGB value. If you are writing a value to an image in an sRGB format, then the system will interpret that value as already being in the sRGB colorspace. So no conversion will be performed; it will be written to the texture as-is. And if blending is active, the sRGB value you wrote will be blended against the sRGB value in the image, in the sRGB colorspace.
Now, when it comes to writing to an sRGB colorspace image, you usually don't want that behavior. If you have a linear RGB value, you want the system to convert that value to the sRGB colorspace (rather than pretending it already is). Equally importantly, when blending is active, you want the value in the sRGB image to be converted into linear RGB, then blended with the linear value written by the fragment shader, and finally converted back into sRGB. Otherwise, blending yields results of dubious accuracy.
To make all that happen, you must glEnable(GL_FRAMEBUFFER_SRGB)
. When this feature is enabled, colorspace conversion happens for any fragment shader output written to any image whose colorspace is sRGB.
This value is disabled by default.
So if you want to write linear RGB values and have them converted to sRGB for display purposes, then you must:
Make sure that the framebuffer image you're writing to uses the sRGB colorspace. For FBOs, this is trivial. But if you're writing to the default framebuffer, then that's something you have to work out with your OpenGL initialization code.
Enable GL_FRAMEBUFFER_SRGB
when you wish to use colorspace conversion.