C++ OpenGL:Gamma校正图像不';不呈线性

C++ OpenGL:Gamma校正图像不';不呈线性,c++,opengl,glsl,gamma,srgb,C++,Opengl,Glsl,Gamma,Srgb,我正在使用OpenGL进行渲染,当我将线性值写入默认帧缓冲区(无任何gamma校正)时,它们在监视器上显示为线性。这与我认为我所知道的关于伽马校正的一切都背道而驰(如这里所解释的:)。如果没有伽马校正,我希望我的显示器可以看到中等范围的颜色非线性变暗 但这是我实际看到的;首先我没有伽马校正,然后是伽马校正: 这是我的不带gamma校正的片段着色器(在默认帧缓冲区的全屏四边形上绘制)。这将导致左侧的线性图像: out vec4 fsOut0; void main( void ) { /

我正在使用OpenGL进行渲染,当我将线性值写入默认帧缓冲区(无任何gamma校正)时,它们在监视器上显示为线性。这与我认为我所知道的关于伽马校正的一切都背道而驰(如这里所解释的:)。如果没有伽马校正,我希望我的显示器可以看到中等范围的颜色非线性变暗

但这是我实际看到的;首先我没有伽马校正,然后是伽马校正:

这是我的不带gamma校正的片段着色器(在默认帧缓冲区的全屏四边形上绘制)。这将导致左侧的线性图像:

out vec4 fsOut0;

void main( void )
{
    // split the screen into 10 discrete color bands
    float yResolution = 768.0;
    int intVal = int(gl_FragCoord.y / yResolution * 10.0);
    fsOut0.rgb = vec3( float(intVal) / 10.0 );

    fsOut0.a = 1.0;
}
这是添加了gamma校正的着色器(从线性空间到sRGB)。这将导致右侧的图像比线性图像更亮:

out vec4 fsOut0;

void main( void )
{
    // split the screen into 10 discrete color bands
    float yResolution = 768.0;
    int intVal = int(gl_FragCoord.y / yResolution * 10.0);
    fsOut0.rgb = vec3( float(intVal) / 10.0 );

    // gamma correction
    fsOut0.rgb = pow( fsOut0.rgb, vec3(1.0/2.2) );

    fsOut0.a = 1.0;
}
我只是通过查看颜色,使用Photoshop中的颜色选择器,查看色带之间RGB值的差异,来验证颜色是否是线性的。对于线性外观图像,每种颜色之间的差异(大部分)是恒定的

我还尝试请求支持sRGB的默认帧缓冲区。在这种情况下,在没有伽马校正的情况下写入线性值看起来就像第二个图像(非线性)

我做错了什么?或者是我的两台显示器都校准错误,Photoshop不能在线性空间中选择颜色?或者我的“非线性”图像实际上是正确的线性结果,但对我的眼睛来说它似乎不是线性的

我的问题有点重复:
不幸的是,被接受的答案非常令人困惑,而我能够理解的部分似乎相互矛盾,或者至少没有为比回答者知识更少的人充分解释。

好吧,你的左右图片都是预期的。他们非常好,是的,我知道我的东西

这只是因为我们的眼睛也不是很线性,例如,1/5的线性强度(发光强度)被认为是“白色亮度的一半”。这是你在右边看到的,在校正后的图像中,靠近底部

这就是gamma首先出现在那里的原因——通过模仿眼睛的反应来帮助编码。看,gamma使非线性渐变看起来是线性的


然而,一个物理上线性的斜坡(如右图)与被认为是线性的完全相反。请记住,现实世界有一个相当大的动态范围(就发光强度而言),我们的眼睛正在对此进行补偿。这让你感到困惑,但与其他许多人不同的是,你的数字是正确的。

“在photoshop中使用颜色选择器”这样做行不通。这是监视器伽马,不是帧缓冲区伽马。如果将线性值写入fb,ypu将从fb读取线性值。您需要测量来自监视器的光线。@n.m.我的印象是颜色选择器值与帧缓冲区值不同。(因此Photoshop将图像存储在sRGB中,然后在颜色选择器中显示数字之前转换为线性RGB)。我正在用眼睛测量显示器发出的光。我认为伽马校正应该使颜色呈线性。“将图像存储在sRGB中”sRGB从何而来?@n.m.这超出了我的理解。你不知怎么把图像输入了photoshop。怎么做?这或多或少是它的复制品: