我一直假设我的伽马校正管道应该如下:
GL_SRGB8_ALPHA8)中加载的所有纹理使用sRGB格式,因为所有艺术程序都会对其文件进行预伽玛校正.从GL_SRGB8_ALPHA8着色器中的纹理采样时,OpenGL将自动转换为线性空间.请注意,在我的情况下,最终的颜色写入涉及我从FBO(线性RGB纹理)写入后缓冲区.
我的假设受到挑战,好像我在最后阶段进行了伽马校正,我的颜色比它们应该更亮.我设立了由我的价值灯光绘制纯色{255,106,0},但是当我使我得到的{255,171,0}(由打印筛选和颜色采摘确定).而不是橙色我变黄了.如果我没有在最后一步Gamma校正我得到完全相同的{255,权值106,0}.
根据一些资源,现代液晶屏幕模仿CRT伽玛.他们总是吗?如果没有,我怎么知道我是否应该伽马正确?我在其他地方出错了吗?
我现在已经注意到,即使我用光写的颜色是正确的,我使用纹理颜色的地方也不正确(但是如果没有伽马校正,我的预期会更暗).我不知道这种差异来自何处.
在尝试GL_RGBA8我的纹理而不是之后GL_SRGB8_ALPHA8,即使在光照计算中使用纹理值(如果我将光的强度减半,输出颜色值减半),一切看起来都很完美.
我的代码不再考虑任何地方的伽玛校正,我的输出看起来正确.
这让我更加困惑,不再需要/使用伽玛校正?
经过一些实验后,我对这里的几点感到困惑.
1 - 大多数图像格式都是非线性存储的(在sRGB空间中)
我加载了一些图像(在我的例子中是.png和.bmp图像)并检查了原始二进制数据.在我看来,好像图像实际上是在RGB颜色空间中,就好像我将像素值与图像编辑程序与我在程序中得到的字节数组进行比较,它们完美匹配.由于我的图像编辑器给了我RGB值,这表示存储在RGB中的图像.
我正在使用stb_image.h/.c来加载我的图像并一直加载.png并且没有看到加载时伽玛校正图像的任何地方.我还在十六进制编辑器中检查了.bmps,并且磁盘上的值与它们匹配.
如果这些图像实际存储在线性RGB空间的磁盘上,我应该如何(以编程方式)知道何时指定图像是在sRGB空间中?是否有某种方法可以查询更具特色的图像加载器可能提供的内容?或者由图像创建者来保存他们的图像作为伽马校正(或不校正) - 意味着建立一个约定并遵循它给定一个项目.我问了几位艺术家,他们都不知道伽马校正是什么.
如果我指定我的图像是sRGB,它们太暗了,除非我最后进行伽马校正(如果监视器使用sRGB输出,这是可以理解的,但请参见第2点).
2 - "在大多数计算机上,有效扫描输出LUT是线性的!这意味着什么?"
我不确定我能在你的回复中找到这个想法的结果.
据我所知,经过实验,我测试了所有显示器的输出线性值.如果我绘制全屏四边形并在着色器中使用硬编码值对其进行着色而不进行伽马校正,则显示器会显示我指定的正确值.
我从你的回答和我的结果中引用的句子会让我相信现代监视器输出线性值(即不模仿CRT伽玛).
我们的应用程序的目标平台是PC.对于这个平台(不包括带有CRT或真正旧显示器的人),对#1做出任何响应都是合理的,然后对#2进行非伽马校正(即不执行最终的RGB-> sRGB转换 - 手动或使用GL_FRAMEBUFFER_SRGB)?
如果是这样的话,那GL_FRAMEBUFFER_SRGB的平台是什么(或者今天有效使用它的平台),或者是使用线性RGB的监视器真的那么新(假设GL_FRAMEBUFFER_SRGB是2008年推出的那样)?
-
我和我学校的其他一些图形开发人员谈过,并且从它的声音来看,他们都没有考虑伽马校正,他们没有注意到任何不正确的事情(有些人甚至都没有意识到).一个开发人员特别说他在考虑伽玛时得到了不正确的结果,因此他决定不担心伽玛.鉴于我在线/看到我的项目时出现的信息存在冲突,我不确定在我的目标平台项目中该怎么做.
确实是的.如果在信号链中的某处应用了非线性变换,但是所有像素值都未从图像中修改为显示,则该非线性已经预先应用于图像的像素值.这意味着,图像已经处于非线性色彩空间中.
如果我正在检查显示器上的图像,您的回答对我来说是有意义的.可以肯定我是清楚的,当我说我正在研究该图像的字节数组,我的意思是我正在研究在内存中数值的纹理,而不是屏幕上的图像输出(我没有为点#做2) .对我来说,唯一可以看到你说的是真实的方式就是图像编辑器给我的sRGB空间值.
另请注意,我确实尝试检查显示器上的输出,以及修改纹理颜色(例如,除以一半或加倍),输出显示正确(使用我在下面描述的方法测量).
你是如何测量信号响应的? …
我试图在我的着色器中实现一种从法线贴图读取法线的方法。然而,我在读取颜色时发现了一个问题,阻止了它。
我认为诸如 (0, 0, 255)(蓝色)这样的一种颜色相当于着色器中的 (0, 0, 1)。然而,最近我发现,例如,如果我传递颜色为 (128, 128, 255) 的纹理,它并不等于着色器中的 ~(0.5, 0.5, 1)。
在片段着色器中,我编写以下代码:
vec3 col = texture(texSampler[0], vec2(1, 1)).rgb; // texture with color (128, 128, 255)
if(inFragPos.x > 0)
outColor = vec4(0.5, 0.5, 1, 1); // I get (188, 188, 255)
else
outColor = vec4(col, 1); // I get (128, 128, 255)
Run Code Online (Sandbox Code Playgroud)
在 x<0 中,我得到颜色 (128, 128, 255),这是预期的。但在 x>0 中我得到了颜色 (188, 188, 255),这是我没想到的。我希望两种颜色是相同的。我不知道什么?我缺少什么?