【问题标题】:How can I force WebGL to immediately render to a FrameBuffer?如何强制 WebGL 立即渲染到 FrameBuffer?
【发布时间】:2019-06-10 02:46:36
【问题描述】:

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

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

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

【问题讨论】:

    标签: javascript opengl-es webgl textures framebuffer


    【解决方案1】:

    这不是 WebGL 的工作原理。

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

    来自规范:

    命令总是按照接收到的顺序进行处理,尽管在命令的效果生效之前可能存在不确定的延迟 实现。这意味着,例如,必须完全绘制一个图元 在任何后续的影响帧缓冲区之前。这也意味着查询 和像素读取操作返回的状态与所有的完整执行一致 先前调用的 GL 命令...在任何后续命令可以产生任何此类影响之前,必须完成 GL 命令对 GL 模式或帧缓冲区的影响

    不会出现渲染到帧缓冲区并且尚未准备好在绘图调用中使用结果的情况。

    您在 cmets 中声称调用 gl.finish 修复了您的错误,但这很可能只是您的错误实际是巧合。

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

    【讨论】:

    • 感谢您的意见,经过进一步调查,相信 finish() 在这里没有任何后果。我不再看到这个问题,但是我对代码的结构做了很多更改,所以很难说到底是什么造成了不同。也就是说,我不是在尝试渲染画布,而且您的社论不妥。
    【解决方案2】:

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

    WebGLRenderingContext.flush

    WebGL API 的 WebGLRenderingContext.flush() 方法清空 不同的缓冲区命令,导致所有命令被执行为 尽快。

    WebGLRenderingContext.finish

    WebGL API 块的 WebGLRenderingContext.finish() 方法 执行,直到所有先前调用的命令都完成。

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

    【讨论】:

    • 谢谢!它似乎正在使用finish()。非常感谢。
    • @baadcafe,如果您可以发布一个显示您的问题的最小示例,那就太好了。由于 Gregmans 的评论,我很想删除这个答案。但是删除已接受的答案感觉不对。
    • 对,我在实现双缓冲之前遇到了错误——这不是读取和写入同一个缓冲区的情况
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多