Opengl 和 Webgl:从附加到当前帧缓冲区的纹理中采样

Posted

技术标签:

【中文标题】Opengl 和 Webgl:从附加到当前帧缓冲区的纹理中采样【英文标题】:Opengl and Webgl: sampling from a texture attached to current framebuffer 【发布时间】:2018-10-05 11:51:05 【问题描述】:

我有一个带有两个纹理 t0t1 的帧缓冲区。

在第一遍中,我使用多个片段着色器输出渲染给它们。

在第二次通过之前,我会执行以下操作:

打开仅具有一个输出的着色器 将t1 绑定到纹理单元 调用 glDrawBuffers 禁用写入t1 的附件

请注意,t1 用于采样,但仍绑定到当前帧缓冲区。据我了解,这种配置中没有环回。

在 OpenGL 和 WebGL 中都合法吗?

我制作了一个example,它在 Linux 下的 Chrome 和 Firefox 中完美运行,但在 Windows 的两种浏览器中都呈现黑屏。是 D3D 支持的 Webgl 实现中的原因,它是 here 所指出的激进的纹理解除绑定?

【问题讨论】:

【参考方案1】:

这在 WebGL1 和 WebGL2 中都是非法的。如果存在反馈循环,则需要 WebGL 生成INVALID_OPERATION 错误。

From the spec section 6.25

6.25 纹理和帧缓冲区之间的反馈循环

在 OpenGL ES 2.0 API 中,可以对同一纹理进行写入和读取的调用,从而创建反馈循环。它指定了这些反馈循环存在的地方,未定义的行为结果。

在 WebGL API 中,会导致此类反馈循环的此类操作(根据 OpenGL ES 2.0 规范中的定义)将改为生成 INVALID_OPERATION 错误。

正如您在那里指出的那样,在您的情况下听起来可能没有实际的反馈循环,但正如 Nicol 根据规范指出的那样,仍然存在。 This appears to be a bug both Chrome and Firefox.

【讨论】:

【参考方案2】:

据我了解,这种配置中没有环回。

但是有一个。

在 GL 4.5 之前的版本(包括 WebGL)中,feedback loops 会在您从当前附加到帧缓冲区的纹理中读取时发生。如果你现在不写信也没关系。你现在不能写信也没关系。只要它附加到帧缓冲区,您就会从读取它获得未定义的行为(除非它们是从未附加的 mipmap 级别读取)。

在post-GL 4.5(包括 WebGL)或纹理屏障扩展中,这是放松的。但不足以解决你的问题。当您尝试从仍附加到帧缓冲区的图像中读取先前调用中写入的像素时,仍会触发 UB。

因此,您必须更改 FBO 以便不再附加图像,或者您必须发出纹理屏障(如果您可以访问 4.5/ARB/NV_texture_barrier,在桌面 GL 上您可能会这样做)。

【讨论】:

以上是关于Opengl 和 Webgl:从附加到当前帧缓冲区的纹理中采样的主要内容,如果未能解决你的问题,请参考以下文章

glReadPixels 的 OpenGL DSA 等效项

在opengl中启用扩展

帧缓冲区和在opengl中使用着色器

webGL - 如何在帧缓冲区旁边设置模板缓冲区并使用它?

将opengl主帧缓冲区复制到fbo

WebGL:显示深度纹理