伽马校正看起来没有正确校正,这是线性的吗?

4
我想将伽马校正应用到我的OpenGL照明中,但是应用伽马校正后,我的结果看起来一点也不线性。
我还发现了一个非常类似于我的问题的帖子: OpenGL: Gamma corrected image doesn't appear linear,但是它还没有得到答案,也没有讨论实际漫反射光。
为了说明问题,在线性空间中定义了以下4种光颜色:
glm::vec3 lightColors[] = {
    glm::vec3(0.25),
    glm::vec3(0.50),
    glm::vec3(0.75),
    glm::vec3(1.00)
};

将每个光源分离,并对漫反射光照方程应用基本的线性衰减,我得到了以下结果:

wrong gamma

这是片段着色器:

void main()
{           
    vec3 lighting = vec3(0.0);
    for(int i = 0; i < 4; ++i)
        lighting += Diffuse(normalize(fs_in.Normal), fs_in.FragPos, lightPositions[i], lightColors[i]);
    // lighting = pow(lighting, vec3(1.0/2.2));
    FragColor = vec4(lighting, 1.0f);
}

不仅我几乎看不出伽马校正灯光的亮度差异,而且衰减也被伽马校正扭曲了。据我所知,所有计算(包括衰减)都是在线性空间中完成的,通过校正伽马,显示器应该正确地显示它(因为它会再次输出未校正的内容)。根据照明颜色,最右边的圆圈应该比左边的圆圈亮4倍,比第二个圆圈亮两倍,但实际上并非如此。
是我不够敏感无法感知到正确的亮度差异还是出了什么问题?
我尝试的另一件事情是将确切的光颜色输出到默认帧缓冲区,不带伽马校正和带伽马校正。
左侧是未校正的,右侧是带有伽马校正的;红色数字表示Photoshop颜色选择器中的RGB强度。我知道Photoshop RGB值不代表最终输出图像(因为Photoshop不会将RGB值读取为显示器输出)。左侧的图像直观上似乎更好,但基于RGB强度值,我认为右侧的图像确实通过我的片段着色器正确进行了伽马校正;因为每个强度都将通过显示器传递到我的眼睛中,具有正确的强度。例如,0.75强度经过0.88伽马校正后变为0.88 ^ 2.2 = 0.75作为显示器的输出。
右侧的图像是否确实正确?还有,为什么实际照明与其他图像相比如此不同?

伽马校正(gamma correction)是一种非线性操作,用于编码和解码亮度。 - Dale Wilson
抱歉,我不明白那个语句如何有助于此案例,我是否在Gamma方面写错了些什么? - ABHAY
我只是指出了描述中使用“非线性”一词。这是一条评论,而不是答案,因为我没有像derhass那样花时间提供完整的解释,但阅读维基百科文章也会有所帮助。 - Dale Wilson
1个回答

7
你所得到的结果是预期的。你好像混淆了显示器创建的物理辐射亮度和人类感知亮度。后者是非线性的,而简单的伽马模型是一种近似方法。基本上,显示器正在反转人眼的非线性变换,使标准(非线性)RGB空间被感知为线性 - 使用RGB强度0.5被感知为大约是1.0的一半亮度,依此类推。如果在显示伽马校正的灰度级时将色度计或分光仪放置在显示器上,您实际上会看到0.73步骤显示出的亮度为白色电平的50%左右(假设您的显示器不会偏离sRGB模型太多,顺便说一句,sRGB并未使用伽马2.2,而是与伽马2.4结合使用线性段的另一个近似值)。现在的问题是:你想要实现什么?如果您想进行物理上准确的计算,则通常需要在线性颜色空间中工作。但是,亮度比另一个光源低50%的光源对于人来说并不会呈现出一半的亮度,因此您获得的结果基本上是正确的。如果您只想拥有一个在感知亮度上是线性的颜色空间,则可以完全跳过伽马校正,因为sRGB正试图提供这种效果。如果您想要精确的结果,则可能只需要一些色彩校准或小的伽马调整来纠正显示器引入的偏差。

哎呀,所有这些修正级别和非线性空间都让我十分困惑。所以如果我正确理解了:对于物理正确的模型,我目前的建模是正确的(因此50%的光传播出的光子数量只有100%光的一半),因此对于照明模型,这确实是正确的模型。我的问题在于我也期望我的眼睛感知到类似的亮度增加,正如你所说的那样并不正确。 - ABHAY
嗯,如果上下文不清楚,很难说你应该使用什么。至于衰减:好吧,你的伽马校正会非线性地扭曲颜色。然而,我不知道你正在使用哪种衰减模型。看起来你只是线性地做了它,这当然在物理上是完全错误的,因为强度随距离的平方衰减 - 有趣的是,这对人类来说几乎看起来是“线性”的。 - derhass
是的,我使用线性衰减。在非伽马校正模型下看起来相当不错,但在伽马校正下完全失效。既然我完全理解了这些概念,我将尝试一些不同的衰减模型。感谢您清晰简明的回答! - ABHAY
关键点在于:你不能只对计算的一部分进行物理正确性的处理,然后将其与某些在非线性色彩空间中看起来不错的经验模型混合。 - derhass
@MHSFisher:我不知道你期望什么,“伽马校正”只是 y=pow(x,vorrection_exponent);,在GLSL中它的工作方式就像在任何其他编程语言中一样。 - derhass
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接