C++ 基于纯色的OpenGL着色器gamma

C++ 基于纯色的OpenGL着色器gamma,c++,opengl,shader,fragment-shader,C++,Opengl,Shader,Fragment Shader,我想在我的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)); frag

我想在我的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值着色时。在这种情况下,我是否必须在线性空间中变换颜色,并在照明操作后,像对纹理那样变换回gamma空间

这是否适用于我的灯光是彩色的

在这种情况下,我是否必须在线性空间中变换颜色,并在照明操作后,像对纹理那样变换回gamma空间

这取决于:你的颜色是什么颜色空间

你这样做不是因为他们来自哪里;你这么做是因为颜色的真实性。如果该值不是线性的,则必须在使用之前对其进行线性化,而不管它来自何处


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

在OpenGL中,颜色数据和其他类型的数据之间没有很大区别:如果你有一个
vec3
,你可以通过
.xyz
.rgb
访问组件。这些都只是数据

所以问问自己:“我必须在顶点着色器中对顶点位置进行gamma校正吗?”

当然不是,因为顶点位置已经在线性空间中。因此,如果在线性空间中类似地设置顶点颜色,则同样不需要伽马校正

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


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

如果您使用的是非古代硬件,硬件可以为您进行转换(从纹理读取和写入帧缓冲区)。它不仅更快,而且更正确(纹理过滤将正确完成。此外,sRGB转换比pow稍微复杂一点)。关于你的问题:这取决于你的颜色所在的颜色空间。如果它们在sRGB中,那么你必须进行转换。Max,谢谢你的回复,我开始理解你的意思了!事实上,当我想要将颜色设置为vec3(0.5,0.5,0.5)时,我的意思是我想要一个在视觉上介于黑白之间的灰色。这也适用于灯光吗?例如,如果我想要一个介于红色和黑色之间的灯光,我是否必须设置颜色has vec3(0.5,0.0,0.0),然后在进行着色计算之前将其线性化?您不必“必须”执行任何一项。这是你的选择,只要你保持一致。使所有颜色线性化将使着色器代码更简单,但从数字上直观显示颜色/灯光的强度可能会更困难。反之亦然,如果你选择非线性颜色。@Poulp:“如果我想要一个介于红色和黑色之间的光,例如”没有这样的东西。这是以最大光强度(即最大“红色”)为前提的,这在现实世界中是不存在的。再次,非常感谢你的帮助,很抱歉我很难理解(我已经读了很多文章)。我不明白如何使我所有的颜色线性或非线性,对我来说,它只是一个向量3,当它为0.0时,没有颜色(或没有光),0.5它在全暗和全色之间(或在无光和全光之间),1.0它是全色(或全光)。如果你有一些例子,它可能真的很棒@Poulp检查这篇维基百科文章只有一条规则:在片段着色器中使用之前,所有颜色都应该是线性的。您可以控制颜色的来源(从纹理采样,直接加载到顶点属性等),从而控制颜色是否经过gamma校正。Nicol,感谢您的回复。老实说,我真的不知道我发送给着色器的颜色是在sRGB还是RGB颜色空间中,对我来说,我只发送了在0.0和1.0之间用三个浮点值编码的颜色。你能给我解释一下如何知道我在什么颜色空间工作吗?@Poulp:你的颜色来源于什么?它们是来自某个3D建模者吗?或者你只是在代码中设置它们?@Poulp:那你为什么选择那种颜色?这些颜色值是从哪里来的?这就是问题。尼科尔,你的问题是对的。事实上,这些颜色来自我屏幕上的颜色选择。。。所以我的颜色在伽马空间。我做了一个小测试来检查:一个盒子的一半用photoshop的jpg纹理,全是128灰色,另一半立方体用vec3(0.5,0.5,0.5)着色,两个立方体的一半在渲染时颜色完全相同。