我是否需要在片段着色器中进行输出伽马校正?

时间:2019-05-19 02:15:34

标签: opengl glsl fragment-shader color-space

当我在片段着色器的def list_recursive(mydict, path=()): if type(mydict) is list: for i, item in enumerate(mydict): list_recursive(item, path=(*path, i)) return for k, v in mydict.items(): if type(v) is str: print(*map( lambda x:f"['{x}']" if type(x) is str else f"[{x}]", (*path, k) ), '=', v, sep='') else: list_recursive(v, path=(*path, k)) 函数中通过fragColor输出颜色时,颜色分量的强度被解释为线性RGB还是sRGB?或者换句话说,我是否必须在我的着色器中执行伽马校正,或者这已经得到解决?

如果没有通用答案,但取决于某些OpenGL属性:如何设置此属性?

为避免造成误解:各自的颜色完全是通过编程生成的,没有纹理等(可能需要 input 伽玛校正)。

1 个答案:

答案 0 :(得分:3)

每个片段着色器的输出都路由到帧缓冲区(based on glDrawBuffers state)中的特定图像。该图像具有格式。该格式定义了相应输出的默认色彩空间解释。

因此,如果您要以线性RGB格式向图像写入值,则系统会将其解释为线性RGB值。如果您要向an sRGB format中的图像写入值,则系统将在sRGB色彩空间中将该值解释为已经存在。因此将不执行任何转换;它将按原样写入纹理。如果启用了混合功能,则您写入的sRGB值将与sRGB色彩空间中图像中的sRGB值混合。

现在,当涉及到写入sRGB色彩空间图像时,通常不需要这种行为。如果您具有线性RGB值,则希望系统将该值转换为sRGB色彩空间(而不是假装已经存在)。同样重要的是,启用混合后,您希望将sRGB图像中的值转换为线性RGB,然后与片段着色器写入的线性值混合,最后转换回sRGB。否则,混合会产生可疑准确性的结果。

要实现所有这些,请must glEnable(GL_FRAMEBUFFER_SRGB)。启用此功能后,写入任何色彩空间为sRGB的任何图像的片段着色器输出都会进行色彩空间转换。

此值默认为禁用。

因此,如果要写入线性RGB值并将其转换为sRGB以用于显示,则必须:

  1. 确保要写入的帧缓冲图像使用sRGB色彩空间。对于FBO,这是微不足道的。但是,如果要写入默认的帧缓冲区,则必须使用OpenGL初始化代码进行处理。

  2. 当您希望使用色彩空间转换时启用GL_FRAMEBUFFER_SRGB