【问题标题】:WebGL is it possible to emulate an asynchronous call to gl.finish()WebGL 是否可以模拟对 gl.finish() 的异步调用
【发布时间】:2018-09-02 18:50:49
【问题描述】:

WebGL 很好而且是异步的,因为您可以发送一长串渲染命令而无需等待它们完成。但是,如果出于某种原因确实需要等待渲染完成,则必须与gl.finish() 同步进行。如果gl.finish接受回调并立即返回肯定会更好吗?

问题:有没有办法可靠地模拟这个?

用例:我将大量顶点渲染到一个大的离屏画布,然后使用drawImage 将此大画布的部分复制到页面上的小画布。我实际上并没有使用gl.finish(),但drawImage() 似乎具有相同的效果。在我的应用程序中,仅当用户执行操作(例如单击按钮)时才会触发重新渲染,并且可能需要数百毫秒。如果在渲染过程中浏览器仍然响应允许滚动等,那就太好了。我特别在寻找 Chrome 解决方案,尽管在 Firefox 和 Safari 中也可以使用的东西会很好。

可能的(错误的)答案:您可以尝试估计渲染需要多长时间,然后设置一个从调用gl.finish() 开始的超时。然而,可靠地对所有大小的顶点缓冲区和所有用户进行这种估计是非常棘手和不准确的。

可能的(非)答案:requestAnimationFrame 可以满足我的需求……但它不会,是吗?

2018 年可能的答案:也许ImageBitmap API 解决了这个问题 - 请参阅MDN docs

【问题讨论】:

  • 你无法从同一页面渲染它,使用 'async' gl.finish() 因为没有异步版本。如果在屏幕外绘制图像被认为是“繁重”的东西,那么您可以使用 Web Worker 生成它,然后使用这样的图像返回 postMessage 并将其绘制到画布上。这会稍微节省性能,但绘图仍然必须同步。降低画布的分辨率也可能会加快速度。
  • @MaksimsMihejevs - 从 Web Worker 渲染图像将是异步的,但它将使用 CPU 而不是 GPU,因此速度会慢得多。 (你不能从 WebWorkers 访问 WebGL。)
  • 我一直在谈论更多关于画布 2d 上下文的内容,正如您提到的 drawImage

标签: webgl


【解决方案1】:

您已经部分回答了:drawImage() 确实具有类似完成的行为,因为它强制所有未完成的绘图命令在读回图像数据之前完成。问题是即使gl.finish() 做了你想做的事,等待渲染完成,你仍然会像现在一样使用它。渲染完成时主线程将被阻塞,从而中断用户与页面交互的能力。

理想情况下,您在这种情况下想要的是某种回调,它指示一组绘制命令何时完成,而没有实际阻塞等待它们。不幸的是,不存在这样的回调(考虑到浏览器内部的工作方式,提供一个会非常困难!)

在您的情况下,一个不错的中间立场可能是对您认为图像何时准备就绪进行一些智能估计。例如,一旦您在调用drawImage 之前发送了您的绘图调用,请旋转 3 或 4 个requestAnimationFrames。如果您一直观察到它需要更长的时间(10 帧?)然后旋转更长时间。这将允许用户继续正常与页面交互,并且在绘制图像时不会产生延迟,因为内容已经完成渲染,或者因为您在渲染的中途执行同步步骤而产生的延迟要少得多。根据您网站的预期用途,非实时渲染甚至可能会在呈现前旋转整整一秒左右。

这当然不是一个完美的解决方案,我希望我能给你一个更好的答案。也许 WebGL 将来会获得查询这种状态的能力,因为它在像你这样的情况下很有价值,但现在这可能是你能做的最好的事情。

【讨论】:

  • 我刚刚阅读了您的webgl 2.0 post。我认为同步对象可以解决这里的问题是对的吗?
猜你喜欢
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 2013-12-18
相关资源
最近更新 更多