webGL 绑定缓冲区不工作

webGL bindBuffer not working

当试图在 webgl 中显示一些不同形状的对象时,我发现在渲染时只使用了最新创建的缓冲区。这看起来很奇怪,因为我每次都在渲染之前绑定当前缓冲区:

gl.useProgram(this.program);
gl.enableVertexAttribArray(this.a_Position);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);

gl.uniformMatrix4fv(this.u_ModelMatrix, false, MVPMatrix.elements);
gl.uniform4fv(this.u_FragColor, this.color);

gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.disableVertexAttribArray(this.a_Position);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

因此,为了测试最基本的示例,我尝试依次创建两个缓冲区并查看将使用哪一个:

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.enableVertexAttribArray(this.a_Position);
// gl.enableVertexAttribArray(this.a_UV);
gl.vertexAttribPointer(this.a_Position, 3, gl.FLOAT, false, 3*4, 0);
// gl.vertexAttribPointer(this.a_UV, 2, gl.FLOAT, false, 5*4, 3*4);
gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
         0.5,  0.5, 0,
        -0.5, -0.5, 0,
         0.5, -0.5, 0,
         0.5,  0.5, 0,
        -0.5,  0.5, 0,
        -0.5, -0.5, 0
    ]),
    gl.STATIC_DRAW
);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

var buffer2 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer2);
gl.enableVertexAttribArray(this.a_Position);
gl.vertexAttribPointer(this.a_Position, 3, gl.FLOAT, false, 3*4, 0);
gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
         1,  0.5, 0,
        -0, -0.5, 0,
         1, -0.5, 0,
         1,  0.5, 0,
        -0,  0.5, 0,
        -0, -0.5, 0
    ]),
   gl.STATIC_DRAW
);
this.buffer = buffer;

结果是后面的buffer,(buffer2)每次都被渲染。这是为什么?我错过了什么?

顶点属性指针是全局状态,不是缓冲区的局部状态,当您数据设置到缓冲区时,无需设置顶点属性指针。

A vertexAttribPointer 调用基本上告诉 GPU "hey the positions start at 0 and are 3 floats each" 并且 GPU 通过将属性 pointer 设置为 currently bound buffer address + [=14 来服从=],但是,当您更改缓冲区时,此指针仍然指向 "old" 缓冲区,您需要通过另一个调用 vertexAttribPointer.

来更新它

所以你的缓冲区初始化代码变成:

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
         0.5,  0.5, 0,
        -0.5, -0.5, 0,
         0.5, -0.5, 0,
         0.5,  0.5, 0,
        -0.5,  0.5, 0,
        -0.5, -0.5, 0
    ]),
    gl.STATIC_DRAW
);

然后在渲染代码中将顶点属性指针设置为主动绑定缓冲区:

gl.useProgram(this.program);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.a_Position);

// Set vertex attribute pointer to current buffer
// Note: I adjusted the stride to 0 to make sense
//       in the context of this question/answer
gl.vertexAttribPointer(this.a_Position, 3, gl.FLOAT, false, 0, 0);

gl.uniformMatrix4fv(this.u_ModelMatrix, false, MVPMatrix.elements);
gl.uniform4fv(this.u_FragColor, this.color);
gl.drawArrays(gl.TRIANGLES, 0, 6);