【问题标题】:OpenGL shader gamma on solid color纯色上的 OpenGL 着色器伽玛
【发布时间】:2017-11-10 14:14:28
【问题描述】:

我想在我的 OpenGL 3D 渲染器上实现 gamma 校正,我知道它与 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 值着色时。在这种情况下,我是否必须在线性空间中转换我的颜色,然后在光照操作之后,像我对纹理所做的那样转换回伽马空间?

这适用于我的灯是彩色的吗?

【问题讨论】:

  • 如果您使用的是非古代硬件,硬件可以为您进行转换(从纹理读取和写入帧缓冲区)。它不仅更快,而且更正确(纹理过滤将正确完成。另外,sRGB 转换比 pow 稍微复杂一点)。关于您的问题:这取决于您的颜色所在的颜色空间。如果它们是 sRGB,那么您必须进行转换。

标签: c++ opengl shader fragment-shader


【解决方案1】:

在这种情况下,我是否必须在线性空间中转换我的颜色,然后在光照操作之后,像我对纹理一样转换回伽马空间?

这取决于:您的颜色在哪个色彩空间中?

您没有进行此更正,因为它们来自哪里;你这样做是因为颜色实际上是什么。如果该值不是线性的,那么无论它来自何处,都必须在使用之前对其进行线性化。

你最终要负责把那个颜色放在那里。因此,您必须知道该颜色是在线性 RGB 还是 sRGB 颜色空间中。如果颜色不是线性的,那么您必须先对其进行线性化,然后才能从中获得有意义的数字。

【讨论】:

  • 尼科尔,感谢您的回复。老实说,我真的不知道我发送到着色器的颜色是在 sRGB 还是 RGB 颜色空间中,对我来说,我只是发送用 0.0 到 1.0 之间的三个浮点数编码的颜色。你能解释一下如何知道我在什么颜色空间工作吗?
  • @Poulp:你的颜色的起源是什么?它们来自某些 3D 建模器吗?或者你只是在代码中设置它们?
  • @Poulp:你为什么选择那个特别的颜色?这些颜色值是从哪里来的?这就是问题所在。
  • 尼科尔,你这个问题是对的。事实上,这些颜色来自我屏幕上的颜色选择......所以我的颜色在伽马空间中。我做了一个小测试来检查:纹理一半的盒子带有来自 128 灰色的 photoshop 的 jpg 纹理,一半的立方体用 vec3(0.5,0.5,0.5) 着色,立方体的两半是渲染时颜色完全相同。
【解决方案2】:

在 OpenGL 中,颜色数据和其他类型的数据之间没有太大区别:如果您有 vec3,您可以使用 .xyz.rgb 访问组件。都是数据。

所以问问自己这个问题:“我是否必须对顶点着色器中的顶点位置进行伽玛校正?”

当然不是,因为您的顶点位置已经在线性空间中。因此,如果您在线性空间中同样设置顶点颜色,则无需进行 gamma 校正。

换句话说,您是否将vec3(0.5, 0.5, 0.5) 想象为介于黑白之间视觉上的灰色?然后你需要伽玛校正。

您是否认为它是数学上介于黑白之间的(就可测量的光强度而言)?那么它已经是线性的了。

【讨论】:

  • Max,谢谢你的回复,我开始明白你的意思了!实际上,当我想将颜色设置为 vec3(0.5, 0.5, 0.5) 时,我的意思是我想要一种在视觉上介于黑白之间的灰色。这也适用于光吗?例如,如果我想要红色和深色之间的光,我是否必须将颜色设置为 vec3(0.5,0.0,0.0),然后在进行着色计算之前对其进行线性化?
  • 你不必“必须”做任何一个。这是你的选择,只要你保持一致。将所有颜色设为线性将使您的着色器代码更简单,但可能更难从数字中看到颜色/光线的强度。如果您选择非线性颜色,反之亦然。
  • @Poulp:“例如,如果我想要红色和黑暗之间的光”没有这样的事情。这将预设一个最大的光强度(即最大的“红色”),这在现实世界中并不存在。
  • 再次,非常感谢您的帮助,很抱歉这对我来说很难理解(我已经阅读了很多文章)。我不明白如何使我的所有颜色都为线性或所有颜色为非线性,对我来说,当它为 0.0 时它只是一个 vec3,没有颜色(或没有光),0.5 它介于全黑和全彩之间(或在无光和全光之间),1.0 它是全彩色(或全光)。如果你有一些例子,它可能真的很棒!
  • @Poulp 检查这篇维基百科文章en.wikipedia.org/wiki/… 只有一条规则:在片段着色器中使用之前,所有颜色都应该是线性的。 可以控制颜色的来源(从纹理采样,直接加载到顶点属性等),因此可以控制颜色是否经过伽马校正与否。
猜你喜欢
  • 1970-01-01
  • 2011-04-19
  • 2012-06-06
  • 2022-12-10
  • 2019-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
相关资源
最近更新 更多