【问题标题】:webgl: how to clone the canvas as-iswebgl:如何按原样克隆画布
【发布时间】:2018-03-05 05:41:29
【问题描述】:

我有一个 webgl 画布。它正在不断更新(模拟)。

现在我想冻结画布的当前内容。我不断获得模拟的更新,我需要不断地向可视化器提供这些更新。所以我实现这一点的想法是将当前 webgl 画布的确切状态克隆到一个新的画布上,并隐藏当前的画布,它会继续更新。然后我可以删除冻结的,并且再次显示实时模拟。

我没能做到这一点,我在网上找到了这样的例子:Any way to clone HTML5 canvas element with its content? 仅适用于 2D 画布。

Google 搜索也没有太大帮助。 这个: how to copy another canvas data on the canvas with getContex('webgl')? 看起来很有希望,但我无法弄清楚如何应用它。

【问题讨论】:

  • 虽然这可能是蛮力的方法,但仅存储模拟状态如何?
  • 我一开始就想到了这个,但我的方法没有奏效。重新审视它,它确实做到了。如果您想提供它作为答案,欢迎您

标签: html canvas webgl


【解决方案1】:

在我看来,克隆画布是一个沉重而奇怪的解决方案。

实现您想要做的最简单的方法是防止帧缓冲区呈现(交换,然后清除)到 HTML 画布。这样做,您只需避免在循环期间调用任何 gl.cleargl.drawArraysgl.drawElements

例如,假设您有两个函数,一个运行模拟,另一个运行 GL 绘图:

function simulate() {
  // update simulation here
}

function draw() {
   gl.clearColor(0.0, 0.0, 0.0, 1.0);
   gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
   // do drawing stuff here
   gl.drawArrays(gl.TRIANGLES, 0, 12345);
   // etc...
}

从现在开始,如果您想“冻结”画布内容,您只需停止在全局循环中调用“绘制”函数即可。例如:

function loop() {
  simulate();
  if(!freeze) draw();

  requestAnimationFrame(loop);
}

您可以使用其他方法来达到相同的效果。例如,您可以将场景绘制到纹理上,然后在画布上绘制纹理。通过这种方式,您还可以控制纹理何时被清除并再次绘制,而它仍然呈现在画布中。

但是,要实现渲染到纹理的方法,您需要在代码中进行一些更繁重的修改:您需要一个额外的着色器来在屏幕上绘制纹理,并且需要一些时间来使用 frameBuffer和 renderBuffer 对象。

【讨论】:

  • 对这个答案感到困惑。您不需要 preserveDrawingBuffer: true 来停止绘图并让画布保持原样。
  • 我没有进行深入测试,但据我所知,没有 preserveDrawingBuffer 浏览器会自动清除和交换缓冲区(画布),即使没有明确调用“gl.clear”:@ 987654321@ 您可以通过停止 requestAnimationFrame 循环来实现相同的目标,但 faboolous 希望它的“模拟”在幕后继续。
  • 只有调用cleardraw???才会清除浏览器,所以不需要preserveDrawingBuffer: true
  • 好的,我仔细阅读了规格,你说得对。与 OpenGL(我们完全控制帧缓冲区)相比,WebGL“自动化”行为有时对我来说很奇怪。我将编辑我的答案。
  • 虽然这看起来是一种可能的方法,但我使用的是第三方库,我无法访问内部工作;赞成答案,但不能接受我的情况。不过还是谢谢
猜你喜欢
  • 2017-08-19
  • 2012-05-20
  • 2017-03-22
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多