【问题标题】:GL_FRAMEBUFFER_SRGB_EXT banding problems (gamma correction)GL_FRAMEBUFFER_SRGB_EXT 条带问题(伽马校正)
【发布时间】:2013-04-01 12:54:13
【问题描述】:

考虑以下代码。 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);

【问题讨论】:

    标签: opengl rendering gamma


    【解决方案1】:

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

    但是,我假设您只是忘记了其中的 if 声明。我假设如果帧缓冲区支持 sRGB,则跳过循环并直接上传数据。所以相反,我会解释为什么你会被绑起来。

    因为您要求的 OpenGL 操作执行以下操作,所以您得到了条带化。对于您指定的每种颜色:

    1. 将浮点数限制在 [0, 1] 范围内。
    2. 将浮点数转换为无符号、标准化、8 位整数。
    3. 使用无符号、标准化、8 位颜色生成片段。
    4. 将无符号、标准化、8 位片段颜色从线性 RGB 空间转换为 sRGB 空间并存储。

    步骤 1-3 都来自于 glDrawPixels 的使用。您的问题是第 2 步。您希望将浮点值保留为 floats。然而,您坚持使用固定功能管道(即:glDrawPixels),它强制将浮点数转换为无符号标准化整数。

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

    简而言之:停止使用glDrawPixels

    【讨论】:

    • 当然,我在使用 GL_FRAMEBUFFER_SRGB 时注释掉了 for 循环,从生成的图像中应该可以看出这一点。好吧,因为除了 GUI 中的轻微延迟之外对我没有任何惩罚,我会让 GPU 独自进行实际的光线追踪。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    相关资源
    最近更新 更多