请考虑以下代码。 imageDataf是一个浮点*。事实上,正如代码所示,它由光线跟踪器创建的float4值组成。当然,颜色值在线性空间中,我需要对它们进行伽马校正,以便在屏幕上输出。 所以我能做的是一个简单的for循环,伽马校正为2.2(参见for循环)。此外,我可以使用GL_FRAMEBUFFER_SRGB_EXT,它几乎可以正常工作,但有“条带”问题。
左边是使用GL_FRAMEBUFFER_SRGB_EXT,右边是手动伽马校正。右图看起来很完美。在某些显示器上发现它可能会有一些困难。有没有人知道如何解决这个问题?我想对“免费”进行伽马校正,因为CPU版本使GUI有点滞后。请注意,实际的光线跟踪是在另一个使用GPU(optix)的线程中完成的,所以实际上它的渲染性能一样快。
GLboolean sRGB = GL_FALSE;
glGetBooleanv( GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &sRGB );
if (sRGB) {
//glEnable(GL_FRAMEBUFFER_SRGB_EXT);
}
for(int i = 0; i < 768*768*4; i++)
{
imageDataf[i] = (float)powf(imageDataf[i], 1.0f/2.2f);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
glDrawPixels( static_cast<GLsizei>( buffer_width ), static_cast<GLsizei>( buffer_height ),
GL_RGBA, GL_FLOAT, (GLvoid*)imageDataf);
//glDisable(GL_FRAMEBUFFER_SRGB_EXT);
答案 0 :(得分:3)
启用GL_FRAMEBUFFER_SRGB
时,这意味着OpenGL将假定片段的颜色位于线性颜色空间中。因此,当它将它们写入sRGB格式图像时,它会将它们从内部转换为sRGB。除了......您的像素不是线性的。您已将它们转换为非线性色彩空间。
但是,我假设您只是忘记了if
语句。我假设如果帧缓冲区支持sRGB,则跳过循环并直接上传数据。所以相反,我会解释你为什么要绑扎。
您正在进行绑定,因为您要求的OpenGL操作执行以下操作。对于您指定的每种颜色:
步骤1-3全部来自glDrawPixels
的使用。您的问题是第2步。您希望将浮点值保持为浮动。然而,你坚持使用固定功能管道(即:glDrawPixels
),强制从float到无符号规范化整数的转换。
如果您将数据上传到浮动纹理并使用适当的片段着色器来渲染此纹理(即使只是一个简单的gl_FragColor = texture(tex, texCoord);
着色器),您也可以。着色器管道使用浮点数学,而不是整数数学。所以不会发生这样的转换。
简而言之:停止使用glDrawPixels
。