OpenGL着色器在纯色上的伽马校正

3

我希望在我的OpenGL 3D渲染器上实现伽马校正,我知道这对于在sRGB中加载的纹理非常重要,因此我这样做:

vec4 texColor;
texColor = texture(src_tex_unit0, texCoordVarying);
texColor = vec4(pow(texColor.rgb,vec3(2.2)),1.0);
vec4 colorPreGamma = texColor * (vec4(ambient,1.0) + vec4(diffuse,1.0));
fragColor =  vec4(pow(colorPreGamma.rgb, vec3(1.0/gamma)),1.0);

但我的问题是关于纯色的,当我想要点亮的3D物体表面不是贴图而仅由每个顶点的RGB值着色时。在这种情况下,我是否需要将我的颜色转换为线性空间,然后在光照操作之后再像处理纹理一样转换回伽马空间?
当我的光源有颜色时,这是否适用?

2
如果您使用的不是古老的硬件,硬件可以为您执行转换(从纹理读取和写入帧缓冲区)。这不仅更快,而且更正确(纹理过滤将被正确地执行。此外,sRGB转换比pow函数稍微复杂一些)。关于您的问题:这取决于您的颜色空间。如果它们是在sRGB中,则必须进行转换。 - geza
2个回答

1
在这种情况下,我是否需要将我的颜色转换为线性空间,然后在光照操作后再转换回伽马空间,就像我对纹理所做的那样?
这取决于您的颜色处于哪个颜色空间中。
您之所以要进行这种校正,不是因为它们来自何处,而是因为颜色实际上是什么。如果值不是线性的,则必须在线性化之后才能使用它,无论它来自何处。
您最终负责放置该颜色。因此,您必须知道该颜色是处于线性RGB还是sRGB颜色空间中。如果颜色不是线性的,则必须将其线性化,然后才能从中获得有意义的数字。

Nicol,感谢您的回复。老实说,我不知道我发送到着色器的颜色是在sRGB还是RGB颜色空间中,我只是发送了由三个0.0到1.0之间浮点数编码的颜色。您能解释一下如何知道我正在使用哪种颜色空间吗? - Poulp
@Poulp:你的颜色是从哪里来的呢?是从某个3D建模器中导出的吗?还是直接在代码中设置的? - geza
@Poulp:你为什么选择了那种特定的颜色?这些颜色值是从哪里来的?这就是问题所在。 - Nicol Bolas
Nicol,你对这些问题的回答是正确的。实际上,这些颜色来自我屏幕上的取色器...所以我的颜色都在伽马空间中。我做了一个小测试来验证:用 Photoshop 中的 jpg 纹理将一个盒子的一半涂成 128 灰度,另一半用 vec3(0.5,0.5,0.5) 来染色,当渲染时,这两个半盒子的颜色完全相同。 - Poulp

0
在OpenGL中,颜色数据和其他类型的数据之间没有什么明显的区别:如果你有一个vec3,你可以通过.xyz.rgb访问其组件。这些只是数据。
所以你要问自己:“我需要在顶点着色器中对我的顶点位置进行伽马校正吗?”
当然不需要,因为你的顶点位置已经处于线性空间中。所以如果你也在线性空间中设置顶点颜色,那么同样不需要进行伽马校正。
换句话说,你认为vec3(0.5, 0.5, 0.5)代表的是一种视觉上介于黑色和白色之间的灰色吗?那么你就需要进行伽马校正。
如果你将其看作是在可测光强度方面介于黑色和白色之间的数学上的一半,那么它已经是线性的了。

Max,感谢您的回复,我开始理解您的意思了!确实,当我想将颜色设置为vec3(0.5, 0.5, 0.5)时,我的意思是我想要一种在视觉上介于黑色和白色之间的灰色。这也适用于光吗?例如,如果我想要一种介于红色和暗色之间的光,我是否需要将颜色设置为vec3(0.5,0.0,0.0),然后再进行线性化处理,然后再进行着色计算? - Poulp
你没有“必须”做其中任何一个。这是你的选择,只要你保持一致即可。使所有颜色线性化将使你的着色器代码更简单,但可能更难以从数字上直观地看出颜色/光的强度。反之亦然,如果你选择非线性颜色,则会相应变化。 - Max
@Poulp:“如果我想要一个介于红色和黑暗之间的光。”这是不存在的。这会预设一个最大的光强度(也就是最大的“红”),但在现实世界中并不存在这样的东西。 - Nicol Bolas
再次感谢您的帮助,很抱歉我很难理解(我已经阅读了很多文章)。我不明白如何使我的所有颜色线性或非线性,对我来说它只是一个vec3,当它为0.0时没有颜色(或没有光),0.5它在完全黑和完全彩色之间(或在无光和全光之间),1.0它是完全彩色(或全光)。如果您有一些示例,那就太好了! - Poulp
维基百科关于sRGB的文章涵盖了转换函数。将其翻译成GLSL应该很容易。 - Max
显示剩余2条评论

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