简体   繁体   中英

WebGL draw multiple objects

I am working on WebGL and I have made some classes to make rendering easier. The problem is, that only the first class can be rendered and all other classes aren't rendered. I looked for every array buffer and bind and unbind them when needed but it still doesn't work. This is my class for a 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();
  }
}

These are the classes for ArrayBuffers and VertexAttribPoints:

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);
    }
}

You might have noticed that I print the ID of the VertexAttribPointer and I get: 2 0 1 2 0 1 I have two classes and both of them are using the same pointers, this shouldn't happen, what could lead to this?

From my understanding of OpenGL every buffer etc. is deactivated after the triangles have been drawn. Where is the error that leads to only drawing the first class?

This

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);
    }
}

Needs to be this

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);
    }
}

And your program usage need to be moved to render

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


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

  }
}

You don't actually need any of the unbinds what-so-ever BTW

You can think of bind as similar to just setting global variables.

 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'));

Notice I don't unbind anything. I just bind the things I need for the next function to run. It's the same in WebGL though the state is more complicated

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM