【问题标题】:Calculating average scene brightness in OpenGL在OpenGL中计算平均场景亮度
【发布时间】:2015-08-21 19:43:22
【问题描述】:

我目前正在实现自动调整曝光以在 OpenGL 中与 HDR 一起使用。为此,我需要检索前一帧中所有像素的平均亮度。

我还没有找到任何关于如何做到这一点的可靠解释。据我所知,有两种方法可以解决。

  1. 使用 glReadPixels 将帧缓冲区复制到内存并在 CPU 上平均它们。这可能会非常缓慢,并且不能很好地利用 GPU。
  2. 获取帧并使用线性过滤将其渲染到连续更小的 FBO。这让 GPU 可以完成大部分工作,但需要大量的 FBO(对于 1080p 屏幕大约需要 10 个)。

必须有更好的方法来获得平均场景亮度。有人有什么建议吗?

【问题讨论】:

    标签: opengl framebuffer brightness


    【解决方案1】:

    我想到了两个选项:

    • 使用 glGenerateMipmap 计算 2x2 窗口的平均值,让您获得最小级别的平均场景亮度。这可以使用着色器中的 textureLod 函数来检索。由于每个 mipmap 级别的大小是前一个级别的一半,因此正确的级别将是 log2(max),其中 max 是 GL_MAX_TEXTURE_SIZE 的返回值。
    • 使用计算着色器完成与 glGenerateMipmap 基本相同的操作,但窗口大小更大,这可能会更快(尽管我从未对此进行过测试)。

    【讨论】:

    • 如果我为帧生成 mipmap,我如何从程序代码中最小的 mipmap 读回一个像素?在色调映射着色器中采样前一帧并不是一个真正的选择,因为纹理已被清除并重新用于当前帧。我想在渲染一帧后读取程序代码中的亮度,将其存储,然后在下一帧期间将其作为制服传递给相关着色器。
    • 阅读规范后,我认为这可以通过 glGetTexImage 实现。感谢您的帮助。
    【解决方案2】:

    您的选项 2 与在纹理上使用 glGenerateMipmap 没有太大区别,只是您不需要处理任何客户端对象(如 FBO)。所以基本上,渲染到纹理的第 0 级 mipmap,让 GL 生成 mipmap 金字塔,然后只读取最高级别​​的 1x1 图像,这可能是获得平均颜色值近似值的最简单方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 2019-10-27
      相关资源
      最近更新 更多