【问题标题】:Supporting WebGL1 + WebGL2支持 WebGL1 + WebGL2
【发布时间】:2021-09-25 01:57:47
【问题描述】:

我有一个使用 WebGL1 来渲染东西的库。 它大量使用浮动纹理和实例化渲染。

现在似乎对 WebGL1 的支持很奇怪,有些设备支持例如 WebGL2,这些扩展是核心,但不支持 WebGL1,或者支持它,但不支持扩展。

同时,对 WebGL2 的支持并不令人惊奇。也许有一天会,但不是。

我开始研究支持这两个版本需要什么。

对于着色器,我想我基本上可以摆脱#defineing 的事情。比如#define texture2D texture等类似的东西。

当涉及到扩展时,问题就更大了,因为扩展对象不再存在。 作为一个实验,我尝试将扩展属性复制到上下文对象中,例如gl.drawArraysInstanced = (...args) => ext.drawArraysInstancedANGLE(...args).

在纹理方面,不需要改变太多,在 WebGL1 中运行时可能添加 gl.RGBA8 = gl.RGBA 之类的东西,因此在 WebGL2 中运行时它会“正常工作”。

那么问题来了……有人试过吗? 我担心它会损害性能,尤其是函数调用的额外间接性。 如果假设它可以在 WebGL1 中运行,它也会使阅读代码变得不那么明显。毕竟,没有 WebGL1 上下文有 drawArraysInstanced 或 RGBA8。这也困扰着 Typescript 打字和其他小事。

另一种选择是在整个代码中都有分支。两个版本的着色器(或#ifdefrickery),每个需要纹理格式的地方和每个完成实例化的地方都有很多分支。 到处都是这样的东西是很丑陋的:

if (version === 1) {
  instancedArrays.vertexAttribDivisorANGLE(m0, 1);
  instancedArrays.vertexAttribDivisorANGLE(m1, 1);
  instancedArrays.vertexAttribDivisorANGLE(m2, 1);
  instancedArrays.vertexAttribDivisorANGLE(m3, 1);
} else {
  gl.vertexAttribDivisor(m0, 1);
  gl.vertexAttribDivisor(m1, 1);
  gl.vertexAttribDivisor(m2, 1);
  gl.vertexAttribDivisor(m3, 1);
}

最后,也许还有第三种我没有想到的方法。

有什么建议吗?

【问题讨论】:

    标签: webgl webgl2 webgl-extensions


    【解决方案1】:

    不幸的是,我认为大多数答案主要是基于意见的。

    第一个问题是为什么同时支持?如果您的想法在 WebGL1 上运行良好,那么只需使用 WebGL1。如果您绝对必须拥有 WebGL2 功能,那么请使用 WebGL2 并意识到许多设备不支持 WebGL2。

    如果您打算这样做twgl 尝试通过providing a function that copies all the WebGL1 extensions into their WebGL2 API positions 使其更容易。就像你提到的那样,而不是

    ext = gl.getExtension('ANGLE_instanced_arrays');
    ext.drawArraysInstancedANGLE(...)
    

    你应该这样做

    twgl.addExtensionsToContext(gl);
    gl.drawArraysInstanced(...);
    

    我不相信会有任何明显的性能差异。尤其是因为这些函数每帧只调用几百次,所以包装不会成为代码中的瓶颈。

    重点并不是真正同时支持 WebGL1 和 WebGL2。相反,它只是为了让你编写代码的方式对于两个 API 都是相同的。

    不过,这 2 个 API 还是存在真正的差异。例如,要在 WebGL1 中使用 FLOAT RGBA 纹理,您可以使用

    gl.texImage2D(target, level, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, ...)
    

    在 WebGL2 中是

    gl.texImage2D(target, level, gl.RGBA32F, width, height, 0, gl.RGBA, gl.FLOAT, ...)
    

    在这种情况下,如果您尝试将其称为与 WebGL1 相同的名称,WebGL2 将失败。 There are other differences 也是。

    在 WebGL1 和 WebGL2 中可以正常工作。规范明确指出,组合会在 WebGL2 上产生 RGBA8。

    请注意,您需要 RGBA8 的示例不正确。

    gl.texImage2D(target, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, ...)
    

    最大的不同是,如果您可以使用 WebGL1,则没有理由使用 WebGL2。或者,反之亦然,如果您需要 WebGL2,那么您可能无法轻易退回到 WebGL1

    例如,您提到对着色器使用定义,但是您将如何处理 WebGL2 中不存在于 WebGL1 中的功能。 textureFetch 或 mod % 运算符或整数属性等功能......如果您需要这些功能,您主要需要编写仅 WebGL2 的着色器。如果您不需要这些功能,那么一开始就使用 WebGL2 确实没有意义。

    当然,如果你真的想去做,也许你想在用户有 WebGL2 的情况下制作一个更漂亮的渲染器,如果是 WebGL1,则回退到更简单的渲染器。

    TD;LR IMO 选择一个或另一个

    【讨论】:

    • 更准确地说——我并不是指实际使用 WebGL2 特定的功能。如果对它的支持肯定更大,但现在它似乎徘徊在 50% 左右,这太糟糕了。相反,我希望我当前的代码在 WebGL2 上运行。通常这没有多大意义,但是就像我说的那样,我遇到过用户报告说奇怪的事情,比如支持 WebGL2 而不是支持 WebGL1。这只是为了支持这样的设备,仅此而已。虽然我对 WebGL 帮助代码不感兴趣,但我会检查 twgl 注入扩展的方式,也许他们的代码比我的更好
    • 关于性能 - 确实这不应该是我的担心,设置实例属性等函数的使用通常占我代码的
    • 作为旁注,WebGL2 实际上拒绝了我现有的使用 RGBA 的 texImage2D 调用,但我也没有真正研究它。无论哪种方式,它都可以通过例如“支持”。为 WebGL1 上下文定义 RGBA8=RGBA 和 RGBA32F=RGBA
    • 不应该有任何支持WebGL2但不支持WebGL1的配置。每当你看到这个时就提交一个错误。例外情况是某些扩展在 WebGL1 中不受支持,但在相同系统上的 WebGL2 上可用,例如 draw_buffers 和 shader_texture_lod。
    • 在这种情况下,代码确实不起作用。例如,我也使用 shader_texture_lod,所以在这样的实现中,在 WebGL2 上运行将是我唯一的解决方案。一个人在 github 上报告说有一个 WebGL2 上下文,但没有一个 WebGL1 上下文。去图
    【解决方案2】:

    我在编写我的库的文档时发现了这个问题,它有很多目标,但其中一个正是这个 - 同时支持 WebGL1 和 WebGL2,以实现更高的跨设备兼容性。

    https://xemantic.github.io/shader-web-background/

    例如,我在BrowserStack 中发现三星手机不支持在 WebGL1 中渲染到浮点纹理,而在 WebGL2 中对它们来说非常好。同时,WebGL2 将永远不会出现在 Apple 设备上,但对半浮点纹理的渲染得到了很好的支持。

    我的库不提供完整的 WebGL 抽象,而是为片段着色器配置管道。这是 GitHub 上的源代码,其中包含取决于版本的 WebGL 策略代码:

    https://github.com/xemantic/shader-web-background/blob/main/src/main/js/webgl-utils.js

    因此,要回答您的问题,这是可行且可取的,但是对于每个 WebGL 功能,以一种完全通用的方式来完成它可能会非常具有挑战性。我想第一个要问的问题是“共同点是什么?”就支持的扩展而言。

    【讨论】:

      猜你喜欢
      • 2017-09-24
      • 1970-01-01
      • 2017-08-21
      • 2013-10-03
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-08
      相关资源
      最近更新 更多