GL_FRAMEBUFFER_SRGB_EXT绑扎问题(伽马校正)

时间:2013-04-01 12:54:13

标签: opengl rendering gamma

请考虑以下代码。 imageDataf是一个浮点*。事实上,正如代码所示,它由光线跟踪器创建的float4值组成。当然,颜色值在线性空间中,我需要对它们进行伽马校正,以便在屏幕上输出。 所以我能做的是一个简单的for循环,伽马校正为2.2(参见for循环)。此外,我可以使用GL_FRAMEBUFFER_SRGB_EXT,它几乎可以正常工作,但有“条带”问题。

img

左边是使用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);

1 个答案:

答案 0 :(得分:3)

启用GL_FRAMEBUFFER_SRGB时,这意味着OpenGL将假定片段的颜色位于线性颜色空间中。因此,当它将它们写入sRGB格式图像时,它会将它们从内部转换为sRGB。除了......您的像素不是线性的。您已将它们转换为非线性色彩空间。

但是,我假设您只是忘记了if语句。我假设如果帧缓冲区支持sRGB,则跳过循环并直接上传数据。所以相反,我会解释你为什么要绑扎。

您正在进行绑定,因为您要求的OpenGL操作执行以下操作。对于您指定的每种颜色:

  1. 将浮动夹紧到[0,1]范围。
  2. 将浮点数转换为无符号,标准化的8位整数。
  3. 使用无符号,标准化的8位颜色生成片段。
  4. 将无符号,标准化的8位片段颜色从线性RGB空间转换为sRGB空间并存储它。
  5. 步骤1-3全部来自glDrawPixels的使用。您的问题是第2步。您希望将浮点值保持为浮动。然而,你坚持使用固定功能管道(即:glDrawPixels),强制从float到无符号规范化整数的转换。

    如果您将数据上传到浮动纹理并使用适当的片段着色器来渲染此纹理(即使只是一个简单的gl_FragColor = texture(tex, texCoord);着色器),您也可以。着色器管道使用浮点数学,而不是整数数学。所以不会发生这样的转换。

    简而言之:停止使用glDrawPixels