使用 WebGL API 做数学

Using WebGL API to do math

标题说明了一切,但我的问题是,是否可以在浏览器中使用 WebGL API(例如 Google Chrome)来做一些数学题?

假设我想使用 WebGL API 将两个数字相乘,这通常可行吗?如果可行,我该怎么做?

抱歉没有分享任何代码,因为我没有想出任何答案。

嗯,我认为对你的问题最准确的回答是是和否。一方面,整个 GPGPU(图形处理器上的计算)源于使用着色器和一些 hack 来解决一些模拟和数学问题。另一方面,整个 "hacks" 部分使它变得有些困难,并且只对一小部分问题真正有价值。特别是那些受益于大规模并行计算的问题。

据我所知,最常见的模式是使用片段着色器计算纹理的一些值。但是,也有局限性。首先,如果没有扩展,您可以从 WebGL 获得的最好的是 RGBA8 纹理,这极大地限制了计算精度。但是有一个扩展提供带有浮动颜色通道的纹理(如果我没记错的话,还有渲染缓冲区)。此外,将结果复制回 JS 的成本可能很高。

即将推出的 WebGL2 具有更强大的功能,可以以变换反馈、几何着色器和更多纹理和缓冲区格式的形式在 GPU 上进行计算。

只是将 2 个数字相乘并不是您想要在 WebGL 中做的事情。将 2 个数字相乘需要 50-70 次设置调用。

如果你想将 200 万个数字乘以 200 万个其他数字,那么这更适合 WebGL。有很多使用 GPU 进行数学运算的示例。首先,GPU 所做的只是数学运算。恰好人们要求它做的最常见的数学是渲染 3D 或 2D 图形。

您需要搜索的字词是GPGPU

弄清楚如何调整解决方案以适应 how GPUs work 是一门艺术。

WebGL从纹理读取数据和向纹理写入数据的基本点。什么是纹理?它们实际上只是值的二维数组。因此,您将数据放入那些二维数组(纹理)中,然后使用 WebGL 从这些二维数组(纹理)中读取数据并将数据写入其他二维数组(纹理)。

与普通计算的最大区别是

  1. 至少在 WebGL 1 中,从纹理读取数据在每个方向上由 0.0 到 1.0 的值寻址。要从二维数组(纹理)中获取特定值,您必须计算其归一化坐标值(纹理坐标)。

    假设 xy 是一个 ivec2 表示二维数组中的 2 个整数索引,我们可以计算从二维数组(纹理)中获取值所需的归一化坐标

    vec2 uv = (vec2(xy) + 0.5) / textureDimensions;
    vec4 value = texture2D(2dArrayOfValuesTexture, uv);
    

    在 WebGL 2 中,我们不必这样做。我们可以做到

    vec4 value = textureFetch(2dArrayOfValuesTexture, xy, 0);
    
  2. 您没有随机访问权限进行写入

    一般来说,WebGL 按顺序写入目标二维数组(纹理),这可能会妨碍您的操作。有时还有, workarounds.

  3. 您无法立即访问以前的结果。

    一般来说,如果您要计算 10000 个答案,您可以随时参考以前的答案。换句话说,当您计算答案 3766 时,您可以参考答案 0 到 3765。

    尽管在 WebGL 中,您在计算完所有答案之前无法访问之前的任何答案。当然,一旦你计算了所有这些,你就可以将这些答案传回另一个计算。基本上是在一个巨人"batch calculation"期间,答案不能相互引用。

正如基里尔指出的那样,也存在一些限制。 WebGL 1.0 具有浮点纹理,因此很容易获取数据。获取数据需要更多的工作,将答案编码为 8 位 4 通道纹理,读取结果,然后将它们解码回答案,但有很多人这样做。 WebGL 2 将不再需要执行 encode/decode 步骤。