0

我有一些 OpenGL 代码在不同硬件上的行为不一致。我有一些代码:

  1. 创建渲染缓冲区并将纹理绑定到其颜色缓冲区(纹理 A)
  2. 将此渲染缓冲区设置为活动,并调整视口等
  3. 激活像素着色器(在本例中为高斯模糊)。
  4. 将四边形绘制到全屏,上面带有纹理 A。
  5. 取消绑定渲染缓冲区等。

在我的开发机器上,这工作正常,并且具有“就地”模糊纹理的预期效果,但是在其他硬件上这似乎不起作用。

我把它归结为两种可能性。

A)对自己进行渲染缓冲区渲染不应该工作,并且由于某种侥幸而只能在我的开发机器上工作。

或者

B)这种方法应该有效,但还有其他问题。

有任何想法吗?老实说,我很难找到关于这个问题的细节。

4

2 回答 2

2

A) 是正确答案。在读取时渲染到同一个缓冲区是未定义的。它可能有效,也可能无效——这正是正在发生的事情。

在 OpenGL 的情况下,framebuffer_object 扩展有“4.4.3 当绑定纹理对象的图像也附加到帧缓冲区时的渲染”部分,它说明了会发生什么(基本上,未定义)。在 Direct3D9 中,如果您使用该设置,调试运行时会大声抱怨(但它可能会根据硬件/驱动程序工作)。我认为,在 D3D10 中,运行时总是取消绑定用作目标的目标。

为什么这是未定义的?GPU 速度如此之快的原因之一是它们可以做出很多假设。例如,他们可以假设获取像素的单元不需要与写入像素的单元通信。因此可以读取表面,N 个周期后读取完成,N 个周期后像素着色器结束执行,然后将其放入 GPU 上的一些输出合并缓冲区,最后在某个点将其写入内存。最重要的是,GPU 以“未定义”顺序光栅化(一个 GPU 可能按行光栅化,另一个以缓存友好的顺序,另一个以完全不同的顺序),所以你不知道表面的哪些部分将被写入到第一。

所以你应该做的是创建几个缓冲区。在模糊/发光的情况下,两个通常就足够了——先渲染,然后在写入第二个时读取和模糊。如果需要以乒乓方式重复此过程。

于 2009-03-06T07:12:49.590 回答
0

在某些特殊情况下,即使是后备缓冲区也可能就足够了。您根本不执行 glClear,并且您之前绘制的内容仍然存在。当然,需要注意的是,您不能真正从后台缓冲区中读取。但是对于像淡入淡出这样的效果,这是可行的。

于 2009-03-06T09:54:44.193 回答