2

与 OpenGL ES 3 不同,没有gl.mapBufferRange gl.bufferSubData(它存在),在 WebGL 2 中更新统一缓冲区数据的有效方法是什么?例如,PerDraw Uniform 块

uniform PerDraw
{
    mat4 P;
    mat4 MV;
    mat3 MNormal;
} u_perDraw;
4

1 回答 1

2

gl.bufferSubData存在所以看起来你创建一个缓冲区然后创建一个并行类型数组。更新 typedArray 并调用 gl.bufferSubData以将其复制到缓冲区中以进行更新并gl.bindBufferRange使用它。

可能仍然非常快。首先,所有值操作都保留在 JavaScript 中,因此调用 WebGL 的开销更少。如果你有 10 个制服要更新,这意味着你要对 WebGL 进行 2 次调用,而不是 10 次。

TWGL.js 中,我将所有制服的 ArrayBufferViews 生成到一个单一类型的数组中,因此例如给定上面的制服块,您可以这样做

ubo.MV[12] = tx;
ubo.MV[13] = ty;
ubo.MV[14] = tz;

或者作为另一个示例,如果您有一个将数组/类型数组作为目标参数的数学库,您可以执行以下操作

var dest = ubo.P;
m4.perspective(fov, aspect, zNear, zFar, dest);

我遇到的一个问题是处理统一优化。如果我编辑一个着色器,假设我正在调试,我只是output = vec4(1,0,0,1); return;在片段着色器的顶部插入并且一些统一块得到优化,代码将会中断。我不知道在 C/C++ 项目中处理这个问题的标准方法是什么。我猜在 C++ 中你会声明一个结构

struct PerDraw {
  float P[16];
  float MV[16];
  float MNormal[9];
}

所以问题就消失了。在 twgl.js 中,我在运行时有效地生成了该结构,这意味着如果您的代码期望它存在但它不会生成,因为它已被优化然后代码中断。

在 twgl 中,我创建了一个从 JavaScript 对象复制到类型化数组的函数,因此我可以跳过任何优化的统一块,不幸的是这会增加一些开销。您可以自由地直接修改 typearray 视图并在调试时处理损坏或使用结构化复制功能 ( twgl.setBlockUniforms)。

也许我应该让你在 twgl 中从 JavaScript 中指定一个结构并生成它,这取决于你让它匹配统一的块对象。这将使它更像 C++,删除一个副本,并且在调试优化删除块时更容易处理。

于 2016-08-09T02:46:17.917 回答