与OpenGL ES 3不同,没有gl.mapBufferRange
和(它存在),在WebGL 2中更新统一缓冲区数据的有效方法是什么?
例如,PerDraw Uniform块gl.bufferSubData
uniform PerDraw
{
mat4 P;
mat4 MV;
mat3 MNormal;
} u_perDraw;
答案 0 :(得分:2)
gl.bufferSubData
存在,所以看起来你创建一个缓冲区然后创建一个并行的typedArray。更新typedArray并调用
gl.bufferSubData
将其复制到缓冲区进行更新,gl.bindBufferRange
使用它。
那可能仍然很快。首先,所有值操作都保留在JavaScript中,因此调用WebGL的开销更少。如果您有10件制服要更新,则表示您正在进行2次调用WebGL而不是10次。
在TWGL.js中,我将所有制服的ArrayBufferViews生成为单个类型的数组,例如,如果给出上面的统一块,则可以执行
ubo.MV[12] = tx;
ubo.MV[13] = ty;
ubo.MV[14] = tz;
或者作为另一个例子,如果你有一个数学库,它将数组/ typedarray作为目标参数,你可以做像
这样的事情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对象复制到类型化数组的函数,因此我可以跳过任何优化的统一块,不幸的是会增加一些开销。您可以直接修改类型阵列视图并在调试时处理破损或使用结构化复制功能(twgl.setBlockUniforms
)。
也许我应该让你在twgl中用JavaScript指定一个结构并生成它,这取决于你使它与统一块对象匹配。这将使它更像C ++,删除一个副本,并且在调试优化删除块时更容易处理。