首页 文章

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

提问于
浏览
2

我想对我的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倍,亮度是第二个圆圈的两倍,实际上并非如此 .

只是因为我不够灵敏,无法察觉到正确的亮度差异或者是错误的吗?

我试过的其他东西只是将精确的光色输出到默认的帧缓冲区而没有和使用伽马校正 .

gamma output

左是未校正的,右边是伽马校正;红色数字表示Photoshop的颜色选择器的RGB强度 . 我知道Photoshop RGB值不代表最终输出图像(因为Photoshop不会将RGB值读取为监视器输出) . 直觉上左图像似乎更好,但根据RGB强度值,我说最右边的图像确实是由我的片段着色器正确地进行了伽马校正;因为这些强度中的每一个都会通过监视器并以正确的强度进入我的眼睛 . 例如,作为0.88伽马校正的0.75强度变为0.88 ^ 2.2 = 0.75作为监视器的输出 .

正确的形象是否确实正确?而且,与其他图像相比,实际照明怎么样?

1 回答

  • 6

    您获得的结果是预期的结果 .

    您似乎将显示器产生的物理辐射亮度与人类感知亮度混淆 . 后者是非线性的,简单的伽玛模型是一种近似的方法 . 基本上,监视器正在反转人眼的非线性变换,因此标准(非线性)RGB空间被线性感知 - 使用RGB强度0.5被感知为大约亮度的一半1.0,依此类推 .

    如果您在显示伽马校正的灰度级别时将色度计或分光光度计放在显示器上,您实际上会看到0.73步骤将以坎德拉/平方公尺显示白色级别的亮度的大约50%(假设您显示不会偏离sRGB模型,因为不是使用伽马2.2,而是使用线性段与伽马2.4结合,其余为2.2,只是另一种近似值 .

    现在的问题是:你究竟想要实现什么?如果要进行物理精确计算,通常需要在线性颜色空间中工作 . 但是,一个亮度为另一个亮度的50%的光源并不像人类亮一半,你得到的结果基本上是正确的 .

    如果你只想拥有一个与感知亮度呈线性关系的色彩空间,你就可以完全跳过伽马校正,因为sRGB很难尝试提供 . 如果您需要精确的结果,您可能只需要进行一些颜色校准或小的伽玛调整来校正显示器引入的偏差 .

相关问题