WebGL - 我什么时候应该调用bindBuffer和vertexAttribPointer?

问题描述 投票:0回答:1

此问题特定于WebGL,并假设VAO不可用。

我试图通过限制低级状态更改的数量来对3D引擎进行一些改进。但事实证明,我对使用bindBuffervertexAttribPointer的正确方法感到有点困惑。

假设我要绘制2个对象:

  • 第一个对象使用两个缓冲区A和C以及一个元素缓冲区E;
  • 第二个对象使用具有相同元素缓冲区E的缓冲区B和C.

缓冲区A和B使用相同的布局,并且都由位置0引用,而C由位置1引用。

最初,ARRAY_BUFFER_BINDING指向null,而ELEMENT_ARRAY_BUFFER_BINDING指向E.

冗余检查器输出以下(A,B,C,E)=(3,6,5,2):

WebGL Inspector trace

意思就是:

  1. bindBuffer(ELEMENT_ARRAY_BUFFER, [Buffer 2])是不必要的
  2. vertexAttribPointer(1, 2, FLOAT, false, 0, 0)可以避免

由于WebGL可以直接读取ELEMENT_ARRAY_BUFFER_BINDING以了解索引的存储位置,1。对我来说很有意义。

但是,2意味着缓冲区布局存储在VBO中,这是错误的,因为缓冲区A和B在第15和30行看不到冗余。(已经渲染了几个帧,因此它们应该保持其状态)

我想我对drawElements如何知道使用什么缓冲区以及何时/何时存储缓冲区布局感到困惑。

在这个案例中,bindBuffervertexAttribPointer的最佳用途是什么?为什么?

performance optimization webgl vertex-buffer
1个回答
0
投票

实际上我想通过简单地查看redundancy checker的来源就能找到答案。

有两件重要的事情要知道:

  • 缓冲区布局是按位置绑定的,而不是每个VBO绑定的。
  • vertexAttribPointer还会将当前缓冲区分配给给定位置

在内部,WebGL每个位置保留6个参数:

VERTEX_ATTRIB_ARRAY_SIZE_X
VERTEX_ATTRIB_ARRAY_TYPE_X
VERTEX_ATTRIB_ARRAY_NORMALIZED_X
VERTEX_ATTRIB_ARRAY_STRIDE_X
VERTEX_ATTRIB_ARRAY_POINTER_X
VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_X

这是vertexAttribPointer的作用:

function vertexAttribPointer(indx, size, type, normalized, stride, offset) {
    this.stateCache["VERTEX_ATTRIB_ARRAY_SIZE_" + indx] = size;
    this.stateCache["VERTEX_ATTRIB_ARRAY_TYPE_" + indx] = type;
    this.stateCache["VERTEX_ATTRIB_ARRAY_NORMALIZED_" + indx] = normalized;
    this.stateCache["VERTEX_ATTRIB_ARRAY_STRIDE_" + indx] = stride;
    this.stateCache["VERTEX_ATTRIB_ARRAY_POINTER_" + indx] = offset;
    this.stateCache["VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_" + indx] = this.stateCache["ARRAY_BUFFER_BINDING"];
}

最后,WebGL Inspector是真的!状态变化第15行和第30行是必要的,因为VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_0正在改变。

这是最佳追踪:

bindBuffer(ARRAY_BUFFER, A)
vertexAttribPointer(0, 3, FLOAT, false, 0, 0)
drawElements(TRIANGLES, 768, UNSIGNED_BYTE, 0)
bindBuffer(ARRAY_BUFFER, B)
vertexAttribPointer(0, 3, FLOAT, false, 0, 0)
drawElements(TRIANGLES, 768, UNSIGNED_BYTE, 0)

(不再需要bindBuffer(ARRAY_BUFFER, C),因为我们没有做任何事情。)

© www.soinside.com 2019 - 2024. All rights reserved.