释放顶点数组对象的准则是什么,例如绑定到 null?
有趣的是,我似乎可以拥有类似的着色器,我只需要在进行一些分组后发布......还是在每个分组着色器之后执行此操作的最佳做法?
我想在每次绘制调用后都有另一种可能性,即使它们被着色器批处理,但我认为没有必要......
不清楚你在问什么。"何时释放纹理"。当你用完它时?我想你的意思是"解除束缚"而不是"释放"。"释放"在大多数编程中意味着从内存中删除或至少允许从内存中删除。
假设你的意思是何时解绑顶点数组对象(VAO(,事实是你永远不必解绑VAO。
如其他说明,VAO 包含所有属性状态和ELEMENT_ARRAY_BUFFER
绑定,因此
currentVAO = {
elementArrayBuffer: someIndexBuffer,
attributes: [
{ enabled: true, size: 3, type: gl.FLOAT, stride: 0, offset: 0, buffer: someBuffer, },
{ enabled: true, size: 3, type: gl.FLOAT, stride: 0, offset: 0, buffer: someBuffer, },
{ enabled: true, size: 3, type: gl.FLOAT, stride: 0, offset: 0, buffer: someBuffer, },
{ enabled: false, size: 3, type: gl.FLOAT, stride: 0, offset: 0, buffer: null, },
{ enabled: false, size: 3, type: gl.FLOAT, stride: 0, offset: 0, buffer: null, },
{ enabled: false, size: 3, type: gl.FLOAT, stride: 0, offset: 0, buffer: null, },
...
... up to MAX_VERTEX_ATTRIBS ...
]
};
只要您记住gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, someBuffer)
效果状态在当前 VAO 内部,而不是像gl.bindBuffer(gl.ARRAY_BUFFER)
这样的全局状态。
我认为这是最令人困惑的部分。大多数 WebGL 方法都更清楚地说明了受影响的内容gl.bufferXXX
影响缓冲区、gl.texXXX
效果纹理。gl.renderbufferXXX
渲染缓冲区、gl.framebufferXX
帧缓冲区gl.vertexXXX
效果顶点属性 (VAO(。等。。但至少在这种情况下gl.bindBuffer
是不同的,它在绑定到ARRAY_BUFFER
时会影响全局状态,但在绑定到ELEMENT_ARRAY_BUFFER
时会影响 VAO 状态。
我的建议是在初始化期间按此顺序执行以下步骤
for each object
1. create VAO
2. create vertex buffers and fill with data
3. setup all attributes
4. create index buffers (ELEMENT_ARRAY_BUFFER) and fill with data
渲染时
for each object
1. use program (if program is different)
2. bind VAO for object (if different)
3. set uniforms and bind textures
4. draw
重要的是要记住,如果你打电话给gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ...)
你会影响当前的VAO。
为什么我要绑定null
VAO?主要是因为我经常忘记上面的段落,因为在VAO之前ELEMENT_ARRAY_BUFFER
是全局状态。因此,当我忘记这一点并随机绑定一些ELEMENT_ARRAY_BUFFER
以便我可以在其中放置一些索引时,我刚刚更改了当前 VAO 中的ELEMENT_ARRAY_BUFFER
绑定。可能不是我想做的事情。 通过绑定null
,比如在初始化我的所有对象和渲染循环之后,那么我不太可能导致该错误。
另请注意,如果我确实想更新某些几何图形的索引,这意味着我想调用gl.bufferData
或gl.bufferSubData
我可以确定我正在以 2 种方式之一影响正确的缓冲区。一个方法是将该缓冲区绑定到ELEMENT_ARRAY_BUFFER
然后调用gl.bufferData
。另一种通过绑定适当的VAO。
如果这没有意义,那么假设我有 3 个 VAO
// pseudo code
forEach([sphere, cube, torus])
create vao
create buffers and fill with data
create indices (ELEMENT_ARRAY_BUFFER)
fill out attributes
现在我有 3 个形状,假设我想更改球体中的索引。我可以用 2 种方式做到这一点
第一,我可以直接绑定球体的ELEMENT_ARRAY_BUFFER
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sphereElementArrayBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER...); // update the indices
这有一个问题,如果绑定了其他一些 VAO,我只是更改了它ELEMENT_ARRAY_BUFFER绑定
第二,我可以绑定球体的VAO,因为它已经绑定了ELEMENT_ARRAY_BUFFER
gl.bindVertexArray(sphereVAO);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, ...); // update the indices
这似乎更安全的海事组织。
重申一下,ELEMENT_ARRAY_BUFFER绑定是VAO状态的一部分。