gl.bufferSubData 存在,所以看起来你创建了一个缓冲区,然后创建了一个并行的 typedArray。更新 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++,删除一个副本,并且在调试优化删除块时更容易处理。