支持WebGL1+WebGL2

支持WebGL1+WebGL2,webgl,webgl2,webgl-extensions,Webgl,Webgl2,Webgl Extensions,我有一个特定的库,它使用WebGL1渲染东西。 它大量使用浮动纹理和实例渲染 如今,对WebGL1的支持似乎很奇怪,一些设备支持WebGL2,其中这些扩展是核心,但不支持WebGL1,或者支持WebGL1,但不支持扩展 同时,对WebGL2的支持并不令人惊讶。也许有一天会这样,但事实并非如此 我开始考虑如何支持这两个版本 对于明暗器,我认为我基本上可以定义事物。例如,定义texture2D纹理和其他类似内容 当涉及到扩展时,问题就更大了,因为扩展对象不再存在。 作为实验,我尝试将扩展属性复制到上

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

如今,对WebGL1的支持似乎很奇怪,一些设备支持WebGL2,其中这些扩展是核心,但不支持WebGL1,或者支持WebGL1,但不支持扩展

同时,对WebGL2的支持并不令人惊讶。也许有一天会这样,但事实并非如此

我开始考虑如何支持这两个版本

对于明暗器,我认为我基本上可以定义事物。例如,定义texture2D纹理和其他类似内容

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

当涉及到纹理时,不需要做太多更改,也许在WebGL1中运行时可以添加类似gl.RGBA8=gl.RGBA的内容,这样在WebGL2中运行时就可以正常工作

那么问题来了…有人试过这个吗? 我担心它会影响性能,尤其是函数调用的额外间接性。 如果假设代码可以在WebGL1中运行,那么读取代码也会变得不那么明显。毕竟,没有WebGL1上下文安装DrawArrayInstanced或RGBA8。这也会影响打字脚本的输入和其他小事情

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

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);
}
最后,也许还有第三种方法我没有想到


有什么建议吗?

不幸的是,我认为大多数答案主要是基于观点的

第一个问题是为什么两者都支持?如果您的想法在WebGL1上运行良好,那么只需使用WebGL1即可。如果您绝对必须具备WebGL2功能,那么使用WebGL2时,您会意识到许多设备不支持WebGL2,Safari在2020年9月还不支持WebGL2,并且可能永远也不支持WebGL2,尽管它似乎最终即将面世

如果你想做的话,就试着让它变得更容易。就像你提到的,而不是

ext = gl.getExtension('ANGLE_instanced_arrays');
ext.drawArraysInstancedANGLE(...)
相反,你是这样做的

twgl.addExtensionsToContext(gl);
gl.drawArraysInstanced(...);
我不相信会有任何明显的性能差异。特别是因为这些函数一帧只调用几百次,所以包装不会成为代码中的瓶颈

但问题并不是同时支持WebGL1和WebGL2。相反,这只是为了使两个API编写代码的方式相同

尽管如此,这两个API之间还是存在真正的差异。例如,在您使用的WebGL1中使用浮动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, ...)
在本例中,如果尝试将WebGL2与WebGL1调用相同,则WebGL2将失败。还有

将在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,你可以使用更简单的渲染器


运输署;LR我选择一个或另一个

不幸的是,我认为大多数答案主要基于观点

第一个问题是为什么两者都支持?如果您的想法在WebGL1上运行良好,那么只需使用WebGL1即可。如果您绝对必须具备WebGL2功能,那么使用WebGL2时,您会意识到许多设备不支持WebGL2,Safari在2020年9月还不支持WebGL2,并且可能永远也不支持WebGL2,尽管它似乎最终即将面世

如果你想做的话,就试着让它变得更容易。就像你提到的,而不是

ext = gl.getExtension('ANGLE_instanced_arrays');
ext.drawArraysInstancedANGLE(...)
相反,你是这样做的

twgl.addExtensionsToContext(gl);
gl.drawArraysInstanced(...);
我不相信会有任何明显的性能差异。特别是因为这些函数一帧只调用几百次,所以包装不会成为代码中的瓶颈

但问题并不是同时支持WebGL1和WebGL2。相反,这只是为了使两个API编写代码的方式相同

尽管如此,这两个API之间还是存在真正的差异。例如,要在中使用浮动RGBA纹理 您使用的bGL1

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, ...)
在本例中,如果尝试将WebGL2与WebGL1调用相同,则WebGL2将失败。还有

将在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,你可以使用更简单的渲染器


运输署;LR IMO选择一个或另一个

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

例如,我发现三星手机不支持在WebGL1中渲染浮点纹理,而在WebGL2中则完全可以。与此同时,WebGL2将永远不会出现在苹果设备上,但渲染为半浮点纹理是非常受支持的

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


因此,要回答您的问题,这是可行和可取的,但对于每个WebGL功能,以完全通用的方式进行这项工作可能会非常具有挑战性。我想首先要问的问题是什么是共同点?在支持的扩展方面。

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

例如,我发现三星手机不支持在WebGL1中渲染浮点纹理,而在WebGL2中则完全可以。与此同时,WebGL2将永远不会出现在苹果设备上,但渲染为半浮点纹理是非常受支持的

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


因此,要回答您的问题,这是可行和可取的,但对于每个WebGL功能,以完全通用的方式进行这项工作可能会非常具有挑战性。我想首先要问的问题是什么是共同点?就支持的扩展而言。

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