WebGL 绘制多个对象

WebGL draw multiple objects

我正在研究 WebGL,我做了一些 classes 来简化渲染。问题是,只有第一个 class 可以呈现,而所有其他 class 都不会呈现。我查找了每个数组缓冲区并在需要时绑定和取消绑定它们,但它仍然不起作用。这是我的 class 的 triangleElementCluster:

function TriangleElementCluster(vertices, uvs, normals, indices, indicesLenght, shader, gl) {
  shader.use();

  var verticesBuffer = new ArrayBufferFloat(vertices, gl);
  var verticesAttribLocation = new VertexAttribPointerFloat(shader.getProgram(), "vertex", 3, 3, 0, gl);

  var uvsBuffer = new ArrayBufferFloat(uvs, gl);
  var uvsAttribLocation = new VertexAttribPointerFloat(shader.getProgram(), "uv", 2, 2, 0, gl);

  var normalsBuffer = new ArrayBufferFloat(normals, gl);
  var normalsAttribLocation = new VertexAttribPointerFloat(shader.getProgram(), "normal", 3, 3, 0, gl);

  var indicesBuffer = new ElementArrayBuffer16(indices, gl);

  verticesBuffer.unbind();
  verticesAttribLocation.unbind();
  uvsBuffer.unbind();
  uvsAttribLocation.unbind();
  normalsBuffer.unbind();
  normalsAttribLocation.unbind();
  indicesBuffer.unbind();




  this.setTexture = function(texture) {
    this.texture = texture;
  }

  this.render = function() {
    verticesBuffer.bind();
    verticesAttribLocation.bind();
    uvsBuffer.bind();
    uvsAttribLocation.bind();
    normalsBuffer.bind();
    normalsAttribLocation.bind();

    indicesBuffer.bind();

    this.texture.activate(gl.TEXTURE0);

    gl.drawElements(gl.TRIANGLES, indicesLenght, gl.UNSIGNED_SHORT, 0);

    verticesBuffer.unbind();
    verticesAttribLocation.unbind();
    uvsBuffer.unbind();
    uvsAttribLocation.unbind();
    normalsBuffer.unbind();
    normalsAttribLocation.unbind();
    indicesBuffer.unbind();
  }
}

这些是 ArrayBuffers 和 VertexAttribPoints 的 classes:

function ArrayBufferFloat(array, gl) {
    this.arrayBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, this.arrayBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);

    this.unbind = function() {
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
    }

    this.bind = function() {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.arrayBuffer);
    }
}

function VertexAttribPointerFloat(shaderProgram, shaderVariableName, elementLenght, stepSize, offset, gl) {
    var attribLocation = gl.getAttribLocation(shaderProgram, shaderVariableName);
    gl.vertexAttribPointer(attribLocation, elementLenght, gl.FLOAT, gl.FALSE, stepSize * Float32Array.BYTES_PER_ELEMENT, offset);
    gl.enableVertexAttribArray(attribLocation);

    console.log(attribLocation);

    this.bind = function() {
        gl.enableVertexAttribArray(attribLocation);
    }

    this.unbind = function() {
        gl.disableVertexAttribArray(attribLocation);
    }
}

您可能已经注意到我打印了 VertexAttribPointer 的 ID,并且我得到:2 0 1 2 0 1 我有两个 classes 并且它们都使用相同的指针,这不应该发生, 什么会导致这种情况?

根据我对 OpenGL 的理解,每个缓冲区等在绘制三角形后都会被停用。导致只绘制第一个 class 的错误在哪里?

这个

function VertexAttribPointerFloat(shaderProgram, shaderVariableName, elementLenght, stepSize, offset, gl) {
    var attribLocation = gl.getAttribLocation(shaderProgram, shaderVariableName);
    gl.vertexAttribPointer(attribLocation, elementLenght, gl.FLOAT, gl.FALSE, stepSize * Float32Array.BYTES_PER_ELEMENT, offset);
    gl.enableVertexAttribArray(attribLocation);

    console.log(attribLocation);

    this.bind = function() {
        gl.enableVertexAttribArray(attribLocation);
    }

    this.unbind = function() {
        gl.disableVertexAttribArray(attribLocation);
    }
}

需要这样

function VertexAttribPointerFloat(shaderProgram, shaderVariableName, elementLenght, stepSize, offset, gl) {
    var attribLocation = gl.getAttribLocation(shaderProgram, shaderVariableName);

    this.bind = function() {
        gl.enableVertexAttribArray(attribLocation);
        gl.vertexAttribPointer(attribLocation, elementLenght, gl.FLOAT, gl.FALSE, stepSize * Float32Array.BYTES_PER_ELEMENT, offset);
    }

    this.unbind = function() {
        gl.disableVertexAttribArray(attribLocation);
    }
}

并且您的程序使用需要移动到渲染

function TriangleElementCluster(vertices, uvs, normals, indices, indicesLenght, shader, gl) {


  this.render = function() {
    shader.use();
    ...

  }
}

你实际上并不需要任何解除绑定的东西顺便说一句

你可以认为绑定类似于设置全局变量。

const state = {
 temp1: 0,
 temp2: 0,
 temp3: 0,
 result: 0,
};

function add() { state.result = state.temp1 + state.temp2; }
function sub() { state.result = state.temp1 - state.temp2; }
function sum() { state.result = state.temp1 + state.temp2 + state.temp3; }

function bind(id, value) { state[id] = value; }
function get(id)         { return state[id]; }

bind('temp1', 1);
bind('temp2', 2);
bind('temp3', 3);
sum();
console.log('sum:', get('result'));
bind('temp1', 4);
bind('temp2', 5);
add();
console.log('add:', get('result'));

注意我没有解绑任何东西。我只是 绑定 下一个功能所需的东西到 运行。尽管在 WebGL 中是相同的 the state is more complicated