1

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

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

// 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

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

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

唯一明显的解决方法是

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

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

4

1 回答 1

2

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

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

但是请记住,平均深度样本会产生很大的不准确性,因为深度值不是线性分布的。

于 2011-11-17T18:47:12.177 回答