在https://www.lighthouse3d.com/tutorials/glsl-tutorial/uniform-blocks/的示例页面中具有以下内容:
但是从概念上讲,这会更正确吗?
这样的想法是,上载到缓冲区(bindBuffer + bufferData)应该与该缓冲区的用途无关-然后,分别为每个着色器,将使用uniformBlockBinding()+ bindBufferBase()来更新这些制服。 ,相关缓冲区何时更改?
答案 0 :(得分:2)
两个都不比另一个更“正确”。他们都工作。但是,如果您正在谈论关注点分离,那么第一个更好地强调正确分离。
glUniformBlockBinding
修改程序;它不会影响缓冲区对象或上下文缓冲区状态的性质。确实,按所有权利,该调用甚至不应位于同一 function 中;它是程序对象设置的一部分。在现代的GL教程中,他们将使用layout(binding=X)
to set the binding,因此该功能甚至不会出现。对于较早的代码,应在创建程序后将其设置为已知的恒定值,然后再单独使用。
因此,在为缓冲区分配存储空间并将其绑定到索引的绑定点之间使用该函数时,会产生一种印象,即他们应该每帧调用glUniformBlockBinding
,这是错误的印象。
说到错误的印象,glBindBufferBase
甚至不应该在那里叫。该代码的其余部分是缓冲区设置代码。在应用程序开始时,只能执行一次。 glBindBufferBase
应该在渲染过程而不是设置过程中被调用。在一个好的应用程序中,该调用不应靠近glGenBuffers
调用。
答案 1 :(得分:0)
添加答案,因为被接受的答案包含许多与WebGL2不相关的信息
在初始化时,您致电uniformBlockBinding
。对于给定的程序,它设置了特定程序将从哪个统一缓冲区索引绑定点获得特定的统一缓冲区。
在渲染时,您调用bindBufferRange
或bindBufferBase
将特定的缓冲区绑定到特定的统一缓冲区索引绑定点
如果您还需要将新数据上传到该缓冲区,则可以调用bufferData
使用伪代码
// at init time
for each uniform block
gl.uniformBlockBinding(program, indexOfBlock, indexOfBindPoint)
// at render time
for each uniform block
gl.bindBufferRange(gl.UNIFORM_BUFFER, indexOfBindPoint, buffer, offset, size)
if (need to update data in buffer)
gl.bufferData/gl.bufferSubData(gl.UNIFORM_BUFFER, data, ...)
请注意,没有“正确”的顺序。这里的问题是,如何更新缓冲区确实取决于您。由于您可能会在一个缓冲区中以不同的偏移量存储多个统一缓冲区数据,因此像上面那样调用gl.bufferData/gl.bufferSubData
确实不是“正确的”,所以这只是100s的一种方式。
WebGL2(GLES 3.0 ES)不支持接受的答案中提到的layout(binding = x)
。 WebGL2中也没有glGenBuffers
这样的东西