与OpenGL ES 3不同,没有gl.mapBufferRange
和(它存在),有效的更新方式是什么WebGL 2 中的统一缓冲区数据?
例如,PerDraw Uniform block gl.bufferSubData
uniform PerDraw
{
mat4 P;
mat4 MV;
mat3 MNormal;
} u_perDraw;
最佳答案
gl.bufferSubData
存在,因此看起来您创建了一个缓冲区,然后创建了一个并行类型数组。更新 typedArray 并调用
gl.bufferSubData
将其复制到缓冲区中以进行更新,并 gl.bindBufferRange
使用它。
这可能仍然非常快。首先,所有值操作都保留在 JavaScript 中,因此调用 WebGL 的开销更少。如果您有 10 个制服需要更新,则意味着您要对 WebGL 进行 2 次调用,而不是 10 次。
在 TWGL.js我将所有制服生成 ArrayBufferViews 到单个类型数组中,因此例如给定上面的制服 block ,您可以这样做
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;
在片段着色器的顶部,一些统一 block 被优化,代码将被破坏。我不知道 C/C++ 项目中处理此问题的标准方法是什么。我想在 C++ 中你会声明一个结构
struct PerDraw {
float P[16];
float MV[16];
float MNormal[9];
}
所以问题就消失了。在 twgl.js 中,我在运行时有效地生成该结构,这意味着如果您的代码期望它存在,但它没有生成,因为它已经过优化,然后代码中断。
在 twgl 中,我创建了一个从 JavaScript 对象复制到类型化数组的函数,这样我就可以跳过任何优化的统一 block ,不幸的是,这增加了一些开销。您可以直接修改类型数组 View 并在调试时处理损坏问题,或者使用结构化复制功能 (twgl.setBlockUniforms
)。
也许我应该让您在 twgl 中从 JavaScript 指定一个结构并生成它,然后由您决定使其与统一 block 对象匹配。这将使它更像 C++,删除一个副本,并且在调试优化删除 block 时更容易处理。
关于webgl2 - 更新 WebGL 2 中的统一缓冲区数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38841124/