使用WebGL而不是2D Canvas制作2D游戏/应用程序是否有任何原因?

170

除了性能外,使用WebGL而不是2D-Canvas进行2D游戏/应用程序开发的理由是什么?

换句话说,WebGL提供了哪些2D功能,这些功能不容易通过2D-Canvas实现?


13
顺便说一句:虽然你不能在同一个画布上同时使用2D和3D上下文API,但是你仍然可以通过使用多个画布来将它们组合起来。WebGL可以将2D画布用作纹理,而2D画布可以使用WebGL画布作为drawImage的来源。 - Philipp
2
有关@Philipp评论的更多细节,请参见此问答 - bluenote10
9个回答

154
从另一个角度看这个问题:
开发人员如何选择一种技术而不是另一种技术?
  • 更好地集成到他们已经构建的系统中
  • 使用更加简便
  • 速度更快
  • 具有更多功能或更适合他们的需求
  • 成本
  • 更平台无关

因此,我将讨论canvas和webGL API在这些方面的差异。


Canvas和WebGL都是JavaScript API。它们在集成(绑定)方面基本相同。它们都被一些库支持,可以加速您的编码。不同的库可以给您不同的组织代码的方式,因此库的选择决定了您的绘图API的结构,但它仍然基本相同(其余的代码如何与其绑定在一起)。如果您使用库,则编写代码的易用性取决于库本身。

如果您从零开始编写代码,则Canvas API要容易学习和理解得多。它只需要最少的数学知识,开发快速简单。

使用WebGL API需要强大的数学技能和对渲染流水线的充分理解。具备这些技能的人比较难找到,生产速度较慢(由于这种代码库的大小和复杂性),因此成本更高。

WebGL更快,并且具有更多功能。毫无疑问,它是一种本地的3D API,可以完全访问渲染流水线,代码和效果执行速度更快,可调整的内容更多。使用WebGL真的没有限制。

Canvas和WebGL都是HTML5的好东西。通常支持其中一个设备也会支持另一个设备。

总之:

  • 合并绘图API代码和其余代码(集成):相似
  • 易用性:
  • (使用库) canvas = webGL
  • (从头开始) webGL << canvas
  • 速度:webGL > canvas
  • 功能:webGL > canvas
  • 成本:webGL要贵得多
  • 平台:非常相似

附言:欢迎讨论。


@摘要,有哪些关于Web GL的好教程?需要多少小时学习? - Pacerier
1
@Pacerier 只需要谷歌一下,前几个结果可能已经足够好了。然而,要想精通WebGL和图形编程通常需要数周甚至数月的时间,而要真正精通则需要数年时间。这不仅仅是你需要学习API的某些随机“库”而已。 - Dragan Okanovic
@AbstractAlgorithm,我的意思是,如果你已经精通编程画布,那么转向Web GL需要多少小时? - Pacerier
@Pacerier 这取决于开发人员以及像Abstract所说的涉及到的开发人员的数学技能。真的没有可以做出的量化。 - scrappedcola
谢谢您的比较。2021年有任何更新吗?还是您认为这个分析仍然适用? - Crashalot
1
@Crashalot 它表现还不错。Canvas 仍然是一个更易于使用的 API,主要用于 CPU 绘图,而 webGL/webGPU 是一种完全暴露的 GPU 绘图 API——你可以更好地控制它并使其运行更快,但可能需要付出开发时间和所需知识等代价。 - Dragan Okanovic

44
最大的优势是管线的可编程性和性能。例如,假设你正在绘制两个相互重叠的方框,并且其中一个被隐藏起来,一些GL实现可以丢弃隐藏的方框。
下面是比较表格。只是为了完整性而添加了Three.js。
Canvas API WebGL Equivalent Three.js Framework Equivalent
缩放 texImage2D + 修改顶点 摄像机
旋转 texImage2D + 修改顶点 摄像机
平移 texImage2D + 修改顶点 摄像机
变换 texImage2D + 修改顶点 摄像机
清除矩形 清除+视口,或texImage2d 纹理
填充矩形 清除+视口,或texImage2d 纹理
描边矩形 texImage2d 纹理
路径 texImage2d + 模板+ 顶点路径 摄像机+对象
填充文本 texImage2d + 模板+ 顶点路径 摄像机+对象+纹理
描边文本 texImage2d + 模板+ 顶点路径 摄像机+对象+纹理
绘制图像 texImage2d 纹理
创建图像数据 在CPU应用中填充texImage2d的缓冲区 CPU应用程序代码
获取图像数据 readpixels readpixels
设置图像数据 在CPU应用中填充texImage2d的缓冲区 在CPU应用中填充texImage2d的缓冲区
+可编程着色器(顶点,片段)
+离屏缓冲区
+高效的深度三维表示
+高效的点(和其他基元)渲染
+便利方法-材质(精灵...)
+便利方法-灯光
+便利方法-场景

“一些GL实现有丢弃隐藏框的空间”,但是你难道不能在JS中检测到被覆盖的部分,从而不重新绘制不必要的内容吗? - Pacerier
1
现在SO的markdown支持表格了,你愿意更新一下吗? - General Grievance

22

根据我在自己的应用上的经验,图形着色器一直是我需要WebGL支持的唯一原因。对于我来说,易用性并不重要,因为这两个框架都可以通过three.js进行抽象。假设我不需要着色器,我允许使用任何一个框架以最大化浏览器/计算机的支持。


18
WebGL相比2D画布,提供了什么2D功能?我认为最大的一个是图形硬件上可编程的片段着色器。例如,在WebGL中,可以在3D硬件上的着色器中实现康威生命游戏。

http://glslsandbox.com/e#207.3

这种2D显示只能在CPU上运行,而不能使用GPU和2D画布。所有的计算都将由JavaScript实现,即使借助Web Workers的帮助,也不会像GPU那样并行。当然,这只是一个例子,各种有趣的2D效果都可以使用着色器来实现。

2
因此,相对于Canvas而言,WebGL对操作系统的负担更大还是更小? - Pacerier
1
我很好奇的是,所有的画布最终都会使用webgl吗?如果它使用预编译的常见用例webgl,比直接使用webgl更高效;或者除非您使用webgl,否则它不会以任何方式与opengl进行交互。 - Dmytro
2
@Dmitry 很好的问题,不同的浏览器可以采用不同的方法来解决这个问题。但是,无论它们如何加速Canvas 2D API,Canvas 2D API本身都不提供可编程着色器或顶点数组缓冲区。它是一个“啰嗦”的API(每个元素绘制一个JavaScript到本地调用),而WebGL的API允许批量数据加载和基于GPU的自定义处理。 - emackey

16

好的,性能将是选择WebGL而不是canvas的最大原因之一,因为当您编写游戏时,它必须快速。但是,选择WebGL而不是canvas还有其他几个原因。如果您正在开发商业游戏应用程序,则可以使用它来编写着色器、灯光和缩放等功能。此外,当显示超过50个精灵时,canvas会变得卡顿。


1
特别是在像安卓平板这样的设备上,由于 JavaScript 运行时会导致 CPU 负载过高,使用 WebGL 的主要原因是将渲染负载转移到 GPU 上。 - Curtis
1
@Xk0n,关于“提供编写着色器、光照和缩放的可能性”,那么这不会变成依赖于GPU吗? - Pacerier
在2D画布上下文中,您仍然可以使用setTransform进行缩放。然而,当从精灵表缩放时,我一直在遇到2D画布中的纹理出血问题,这就是为什么我转向WebGL的原因。我看到了一个教程,它可以防止最近邻采样超出源矩形,这应该可以解决我的边缘出血问题。 - Frank
1
50了?天啊,我差点就要做成数万个瓦片了... - Pangamma
1
@Xk0nSid,您能否详细说明“在50个精灵左右后,画布也会变得很卡顿。”?您有相关链接吗? - Alexis Tyler
我会说直到大约120个精灵之后它才开始变得卡顿,但是再说一遍,我比这晚了两年并且使用全新的电脑...也许这只是技术进步的缘故。 - Daniel

11

在Canvas上你能做的所有事情,在WebGL上也都能做到:Canvas让你可以使用get/putImageData来压缩字节,同时你也可以使用WebGL以编程方式画线条、圆形等。

如果你想进行密集绘图,例如每秒60帧的复杂效果,那么性能差距就很大了。在2D Canvas中很慢的事情在WebGL中可以运行良好。性能是WebGL的基本特点。

但是,WebGL编程非常复杂。看看Canvas是否足够好,或者寻找一个可以减轻痛苦的库。

WebGL的另一个缺点是它不适用于IE(但什么适用呢?)和某些移动平台。请参阅此处以获取兼容性信息:https://caniuse.com/webgl


1
除了现在广泛支持WebGL之外,对于2021年这一观点是否有任何更新?谢谢分享! - Crashalot

8

由于您特别需要一些经典的2D效果,这些效果在canvas中表现不佳:

  • 颜色转换(如闪烁精灵)
  • 重复位图填充
  • 在旋转下平铺地图(在canvas下,某些实现会创建接缝)
  • 深度分层(非常依赖具体实现)
  • 乘法或加法混合

...但是当然您可以手动完成所有操作,包括上述操作,因为您有像素访问权限。但这可能会变得非常慢。理论上,您可以使用emscripten Mesa openGl渲染到canvas。

使用webGL的另一个重要原因是其结果非常易于移植到任何其他地方。这也使得该技能更具价值。

使用canvas的原因是它仍然得到更好的支持,并且如果您学会逐像素进行操作,那么这也是非常有价值的课程。


顺便问一下,WebGL支持多线程吗?你能同时有两个线程绘制屏幕的两个部分吗? - Pacerier
我认为答案是“是和否”,因为Web浏览器本质上是单线程的,所以将要呈现的数据复制到GPU不是多线程的。但是,一旦着色器开始渲染,您将使用图形卡的大规模并行处理,这实际上是同时绘制屏幕的多个部分。如果我错了,请纠正我。 - Kent Weigel
1
谢谢分享。您认为这个分析在2021年仍然正确吗? - Crashalot

4

没有GPU,WebGL无法使用。
这种硬件依赖并不是一个大问题,因为大多数系统都有GPU,但如果GPU或CPU架构发生变化,通过仿真来保留webgl内容可能会很具有挑战性。在旧的(虚拟化的)计算机上运行它是有问题的。

但“Canvas vs WebGL”不必是二元选择。 我实际上更喜欢使用webgl进行效果处理,但其他部分则使用canvas。 当我在虚拟机中运行它时,它仍然可以快速地工作得很好,只是没有效果。

更新:不幸的是,一些浏览器(Windows上的ChromeLinux上的所有应用,其他?)实现了良好的仿真层使检测贫乏/无GPU变得困难。在这些情况下,游戏或用户必须手动禁用WebGL才能获得实际的性能优势......或者在2D实现不良的情况下降级。据说这也可能发生。[感谢gman]


引用页面上的话:“SwiftShader 的性能应该足够好,可以查看简单的 3D 内容。” “工作”,但不适用于游戏。@gman - user185953
1
正确,但是“WebGL没有GPU就无法使用”是错误的。它可能会很慢,但并不是无法使用。如果没有GPU就无法使用,那么在Chrome中使用没有GPU的解决方案就没有任何意义。 - gman

3
作为一项相对较新的技术,WebGL和更为成熟的HTML5画布可供选择,具体取决于您的用户。如果您认为用户会使用移动设备,那么我建议使用HTML5画布;但是如果您希望获得更好的2D渲染效果,则应使用WebGL。因此,您可以这样做:如果用户使用移动设备,请使用HTML5进行渲染;否则,如果他们使用支持WebGL的平台,则使用WebGL。
例如:
 if (window.WebGLRenderingContext) {
     webGLcanvasApp()
         } else if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
     html5CanvasAppFMobile()
    } else {
    html5CanvasApp()
    }

来源:
检测WebGL支持的正确方法?
jQuery中检测移动设备的最佳方法是什么?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接