【问题标题】:Using depth and color buffers with different resolutions (sub-sampled depth buffer)使用具有不同分辨率的深度和颜色缓冲区(子采样深度缓冲区)
【发布时间】:2011-11-17 18:13:01
【问题描述】:

我想使用子采样深度缓冲区来提高程序的性能。就我而言,是否存在伪影或几何体弹出并不重要。

我已经像这样设置了我的帧缓冲区:

// Color attachment
glBindTexture(GL_TEXTURE_2D, colorAttachment);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);

// Depth attachment
glBindRenderbuffer(GL_RENDERBUFFER, depthAttachment);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 160, 90);

// Framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorAttachment, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthAttachment);

然而,现在glCheckFramebufferStatus(GL_FRAMEBUFFER) 返回GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,根据documentation,它代表“并非所有附加的图像都具有相同的宽度和高度”。

有一篇名为“Full-3D Edge Tracking with a Particle Filter”的研究论文在第 3.5 节中描述了他们实际上使用子采样深度缓冲区来提高其应用程序的性能。

次采样深度缓冲区:沿图像边缘的相邻像素密切相关 测试每个单独的边缘像素是多余的。对于单假设跟踪器, 通常将样本点沿边缘分开 10-20 像素的距离。 仅对每第 n 个边缘像素进行采样也减少了所需的图形带宽,并且 所以只有每 4 个像素被采样一次。这里不是显式绘制点画线,而是通过使用 sub-sampled depth buffer (160 x 120) 来实现,因为这进一步实现了 用于清除和填充深度缓冲区的带宽减少。不过,这也 意味着隐藏线移除可能不准确到大约四个像素。除了 由此,系统的准确性不受影响。

唯一明显的解决方法是

  • 使用片段着色器程序查找先前渲染的深度缓冲区以手动应用深度检查。
  • 以较低的分辨率渲染深度缓冲区,然后将其重新采样到较大的分辨率,然后像以前一样使用它。

这两种方法听起来都不是最有效的想法。实现子采样深度缓冲区的最简洁方法是什么?

【问题讨论】:

    标签: objective-c opengl opengl-es-2.0 framebuffer depth-buffer


    【解决方案1】:

    您引用的文档页面指的是 OpenGL ES 1.0 和 2.0。 OpenGL wiki 有更多关于 2.0 和 3.0 之间差异的信息,即从 3.0(和 ARB_framebuffer_object)开始,帧缓冲区纹理可以有不同的大小。但是,如果我没记错的话,当您附加了不同大小的纹理时,实际使用的纹理大小是所有 FBO 附加纹理的交集。我不认为这是你想要的。

    为了减小深度纹理的大小,我建议使用 glBlitFramebuffer 将大纹理转换为较小的纹理。此操作完全在 GPU 上完成,因此速度非常快。然后可以将最终较小的纹理用作着色器中进一步渲染操作的输入,这肯定会节省带宽。不是为每个像素着色器执行执行多个深度值的平均,而是在较小的纹理中对每个纹素执行一次。较小的纹理本身也可以更快地采样,因为它更适合缓存。

    但请注意,平均深度样本可能会产生严重的不准确性,因为深度值不是线性分布的。

    【讨论】:

    • glBlitFramebuffer 将是一个不错的解决方案。但是,它在 iOS 上不受支持。
    • 您可以将 glBlitFramebuffer 替换为仅对纹理进行采样的全屏四边形着色器。众所周知,它通常更快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    相关资源
    最近更新 更多