【问题标题】:Do I need output gamma correction in a fragment shader?我需要在片段着色器中进行输出伽玛校正吗?
【发布时间】:2019-10-05 20:07:22
【问题描述】:

当我通过片段着色器的main() 函数中的fragColor 输出颜色时,颜色分量强度是否解释为线性RGB 或sRGB?或者换一种说法,我是否必须在我的着色器中执行 gamma 校正,或者这已经被处理了?

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

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

【问题讨论】:

    标签: opengl glsl fragment-shader color-space


    【解决方案1】:

    每个片段着色器输出都被路由到帧缓冲区中的特定图像 (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

    【讨论】:

    • "当混合激活时,您希望将sRGB图像中的值转换为线性RGB,然后与片段着色器写入的线性值混合,最后转换回sRGB。" - 除非您的目标用户也是 Photoshop 用户,在这种情况下,如果在线性 RGB 中完成混合,他们会大声抱怨您的混合是错误的。 :-/
    • 谢谢!我阅读了文档,但它非常混乱。比如我当时想,当framebuffer是sRGB的时候,我要写sRGB,当是linear的时候,我可以写linear。
    • 您是否有任何指示我必须寻找以了解如何使默认帧缓冲区(由 GLUT 创建)在 sRGB 中? glutInitDisplayMode 有一个 GL_RGBA 选项,但有关于线性或 sRGB 的注意事项。发现可以用glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)读取这个属性,返回GL_LINEAR,但是好像没有glSetFramebufferAttachmentParameteriv
    • 好吧,我刚刚发现有一个常量GLUT_SRGB,但是在 FreeGLUT 或原始 GLUT 文档中都找不到任何文档如何使用它。
    • @A.Donda:这是glutInitDisplayMode 的参数。此外,您需要问自己一个问题:您是否想继续使用文档记录如此糟糕的工具,或者您是否想切换到维护人员足够关心以使文档保持最新状态的工具,从而使工具可以用吗?
    猜你喜欢
    • 1970-01-01
    • 2014-05-26
    • 2018-12-04
    • 2012-06-06
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    相关资源
    最近更新 更多