如何强制 WebGL 立即渲染到 FrameBuffer?

How can I force WebGL to immediately render to a FrameBuffer?

背景 - 我正在做一个有点像 After Effects 或 Photoshop 的项目 - 你可以操纵各种视觉层,这些层最终会合成在一起。我对 WebGL 中直接可用的混合模式不满意,所以我一直在使用着色器和多通道渲染方案实现新的混合模式。基本上,我将每一层渲染到一个帧缓冲区中,然后在渲染下一层时立即使用帧缓冲区作为源纹理。

我的问题 - 由于片段着色器 运行 是并行的,所以图层不是按顺序渲染的。浏览器尝试并行渲染所有图层,然后将它们合成在一起,这意味着在着色器执行时给定图层的父图层的源纹理为空。因此,无法合成前一层的数据。我可以从广义上说绑定和渲染工作,因为我能够在渲染所有内容后保留复合纹理并在后续帧中使用它,但这不是我想要的。

我的问题 - 如何强制 WebGL 光栅化给定的帧缓冲区,以便我可以立即将其用作纹理?

我认为您可以使用的唯一两个 API 是 flush 和 finish。据我所知,它们在浏览器中的工作方式并不完全符合预期。不过你可以试一试。

WebGLRenderingContext.flush

The WebGLRenderingContext.flush() method of the WebGL API empties different buffer commands, causing all commands to be executed as quickly as possible.

WebGLRenderingContext.finish

The WebGLRenderingContext.finish() method of the WebGL API blocks execution until all previously called commands are finished.

编辑: 如果这些没有达到您的预期,那么您可能可以执行一个最小的 readPixels 调用,该调用将等待管道完成。

WebGL 不是这样工作的。

从 JavaScript 和 WebGL 的角度来看,没有什么是并行运行的。无论您看到什么错误,都可能是代码错误的结果,与并行的 WebGL 运行 无关。

来自规范:

Commands are always processed in the order in which they are received, although there may be an indeterminate delay before the effects of a command are realized. This means, for example, that one primitive must be drawn completely before any subsequent one can affect the framebuffer. It also means that queries and pixel read operations return state consistent with complete execution of all previously invoked GL commands ... the effects of a GL command on either GL modes or the framebuffer must be complete before any subsequent command can have any such effects

不存在渲染到帧缓冲区但未准备好在绘制调用中使用结果的情况。

您在评论中声称调用 gl.finish 修复了您的错误,但这更可能只是巧合,无论您的错误实际上是什么。

Post 如果您认为您已经看到了其他情况,请提交回购协议,因为这将是您浏览器中的一个错误,应该报告。你提到纹理是空的。这听起来更像是您正在尝试呈现 canvas 的内容,并且它们正在被清除,这是规范的一部分。没有看到您的代码,我们无法告诉您真正的问题是什么,但您在问题中写的不太可能。