为什么 canvas 2D 上下文不在幕后使用 WebGL?
Why isn't canvas 2D context using WebGL under the hood?
我经常使用 canvas 2D 上下文,最近也开始学习一些 WebGL。
标题中的问题是在我编写有关如何在 WebGL 中从 2D 上下文实现 context.drawImage()
的教程时出现的。结果类似于 context.drawImage()
(至少非常接近),但速度要快得多,因为它使用的是 WebGL。
理论上,我相信 canvas 2D 上下文中的所有内容都可以在 WebGL 中模拟,从而获得巨大的性能提升。那为什么不呢?
我绝对不是在谈论更改任何语法或任何内容。我真的很喜欢 2D 上下文的简单性。但为什么浏览器不执行该教程在后台执行的操作?
我知道 WebGL 并非在任何地方都得到完全支持,但我仍然认为如果可能的话可以使用它,并使用常规 2D 上下文作为后备。
Canvas2D 确实使用引擎盖下的 GPU,使用与 WebGL 基本相同的 API。
如果您在 WebGL 中实现整个 Canvas 2D 规范,很可能会有相似的速度。 Canvas 支持使用 patterns, drawing with gradients, clipping paths 绘图、任意宽度的线条、端点、连接等...将所有这些功能添加到 WebGL 中实现的 Canvas 中,速度可能会相似。
WebGL 可以 更快的原因是 (a) 因为您可以选择不实现您不打算使用的功能,并且 (b) 因为您可以优化了解自己只会使用某些功能。
作为一个简单的例子,在canvas中你可以用drawImage(someImageElement, x, y)
画一个图像。在 WebGL 中,您首先必须从图像创建纹理,然后使用该纹理进行绘制,以便您手动管理该纹理。 Canvas 实际上必须做同样的事情。它必须将图像加载到纹理中才能绘制它(假设它是基于 GPU 的,canvas 通常是)。但是,它不知道您是否要再次绘制该图像,因此它不能将该图像永远保留为纹理。最简单的实现是将图像复制到纹理、绘制,然后删除纹理。我怀疑 canvas 是做什么的,我猜它有一些从图像中制作的纹理缓存。但是,重点是,它对纹理的管理是隐式的,而在 WebGL 中它是显式的,您必须自己手动管理纹理。
另一个例子是绘制形状。在 WebGL 中,您通常在初始时决定绘制什么形状,设置绘制它们所需的所有数据,然后在渲染时您只需使用您已经设置的形状。在 Canvas 中,更常见的是动态绘制形状,这意味着每次你想绘制形状时,你都使用 moveTo
和 lineTo
命令来绘制形状,这有效地完成了所有每次渲染时都工作,而不是像 WebGL 那样只在初始化时才工作。
这些差异加起来 canvas 更容易,webgl 更快。
我经常使用 canvas 2D 上下文,最近也开始学习一些 WebGL。
标题中的问题是在我编写有关如何在 WebGL 中从 2D 上下文实现 context.drawImage()
的教程时出现的。结果类似于 context.drawImage()
(至少非常接近),但速度要快得多,因为它使用的是 WebGL。
理论上,我相信 canvas 2D 上下文中的所有内容都可以在 WebGL 中模拟,从而获得巨大的性能提升。那为什么不呢?
我绝对不是在谈论更改任何语法或任何内容。我真的很喜欢 2D 上下文的简单性。但为什么浏览器不执行该教程在后台执行的操作?
我知道 WebGL 并非在任何地方都得到完全支持,但我仍然认为如果可能的话可以使用它,并使用常规 2D 上下文作为后备。
Canvas2D 确实使用引擎盖下的 GPU,使用与 WebGL 基本相同的 API。
如果您在 WebGL 中实现整个 Canvas 2D 规范,很可能会有相似的速度。 Canvas 支持使用 patterns, drawing with gradients, clipping paths 绘图、任意宽度的线条、端点、连接等...将所有这些功能添加到 WebGL 中实现的 Canvas 中,速度可能会相似。
WebGL 可以 更快的原因是 (a) 因为您可以选择不实现您不打算使用的功能,并且 (b) 因为您可以优化了解自己只会使用某些功能。
作为一个简单的例子,在canvas中你可以用drawImage(someImageElement, x, y)
画一个图像。在 WebGL 中,您首先必须从图像创建纹理,然后使用该纹理进行绘制,以便您手动管理该纹理。 Canvas 实际上必须做同样的事情。它必须将图像加载到纹理中才能绘制它(假设它是基于 GPU 的,canvas 通常是)。但是,它不知道您是否要再次绘制该图像,因此它不能将该图像永远保留为纹理。最简单的实现是将图像复制到纹理、绘制,然后删除纹理。我怀疑 canvas 是做什么的,我猜它有一些从图像中制作的纹理缓存。但是,重点是,它对纹理的管理是隐式的,而在 WebGL 中它是显式的,您必须自己手动管理纹理。
另一个例子是绘制形状。在 WebGL 中,您通常在初始时决定绘制什么形状,设置绘制它们所需的所有数据,然后在渲染时您只需使用您已经设置的形状。在 Canvas 中,更常见的是动态绘制形状,这意味着每次你想绘制形状时,你都使用 moveTo
和 lineTo
命令来绘制形状,这有效地完成了所有每次渲染时都工作,而不是像 WebGL 那样只在初始化时才工作。
这些差异加起来 canvas 更容易,webgl 更快。