在帧缓冲区和活动纹理之间形成的 WebGL 反馈循环

WebGL feedback loop formed between Framebuffer and active Texture

我有一个 webgl 项目设置,它使用 2 pass 渲染在纹理上创建效果。

一切正常,直到最近 chrome 开始抛出此错误:

[.WebGL-0000020DB7FB7E40] GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture. 

虽然我没有更改我的代码,但这种情况才刚刚开始发生,所以我猜是新的更新导致了这种情况。

我在 SO 上找到 ,指出错误 "happens any time you read from a texture which is currently attached to the framebuffer"。

然而,我已经梳理了我的代码 100 次,但我不相信我正在这样做。所以这就是我的设置方式。

使用统一采样器创建片段着色器。

uniform sampler2D sampler;

创建 2 个纹理

var texture0 = initTexture(); // This function does all the work to create a texture 
var texture1 = initTexture(); // This function does all the work to create a texture 

创建帧缓冲区

var frameBuffer = gl.createFramebuffer();

然后我通过将 html 图像上传到 texture0 并将 texture0 绑定到采样器来开始“2 遍处理”。

然后我绑定帧缓冲区并调用 drawArrays:

gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

为了清理,我解除了帧缓冲区的绑定:

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

编辑:

在我的代码中添加断点后,我发现在我绑定空帧缓冲区之前实际上并没有抛出错误。所以 drawArrays 调用不会导致错误,它绑定了空帧缓冲区之后将其关闭。

Chrome 自版本 83 开始对帧缓冲区和活动纹理反馈循环执行保守检查。这些检查可能过于保守,影响了实际允许的使用。

在这些新检查中 Chrome 似乎不允许将渲染目标绑定到任何纹理槽,即使该槽未被程序使用。

在你的 2 pass 渲染中你可能有类似的东西:

  1. 初始化渲染目标并创建指向帧缓冲区的纹理。
  2. 渲染到目标。

在 1 中,您可能需要使用 gl.bindTexture(gl.TEXTURE_2D, yourTexture) 绑定纹理,然后,在第 2 步之前,使用 gl.bindTexture(gl) 取消绑定纹理.TEXTURE_2D, 空);否则 Chrome 将失败,因为渲染目标被绑定为纹理,即使该纹理未被程序采样。