在以下WebGL代码中我在做什么错?

时间:2019-11-30 20:30:33

标签: webgl

我从一个示例WebGL程序开始,该程序在页面上显示了一个多维数据集。示例代码不使用类。

我希望能够绘制多个可以独立移动的立方体。因此,我添加了一个“多维数据集”类。此类的每个实例都使用其自己的“程序”。我创建了两个对象,但只绘制了第一个对象。不幸的是,显示了后来实例化的对象。例如。在“ ground”下面的代码中显示,而不是“ cube1”。

代码的相关部分在下面。您能看到任何问题吗?我该如何解决?

...
////
class Cube {
  constructor(gl, color) {
    this.gl = gl;
    this.program = initShaders(gl, "vertex-shader", "fragment-shader");

    //// Model buffers and attributes
    [this.pointsArray, this.colorsArray] = cubePointsAndColors(color);
    this.numVertices = 36;
    this.initAttributeBuffers();

    //// Camera Related Uniforms Matrices
    this.modelViewMatrixLoc = gl.getUniformLocation(
      this.program,
      "modelViewMatrix"
    );
    this.projectionMatrixLoc = gl.getUniformLocation(
      this.program,
      "projectionMatrix"
    );
  }

  draw() {
    this.gl.drawArrays(this.gl.TRIANGLES, 0, this.numVertices);
  }

  initAttributeBuffers() {
    // arrange cube color data stuff
    var cBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, cBuffer);
    this.gl.bufferData(
      this.gl.ARRAY_BUFFER,
      flatten(this.colorsArray),
      this.gl.STATIC_DRAW
    );
    var vColor = this.gl.getAttribLocation(this.program, "vColor");
    this.gl.vertexAttribPointer(vColor, 4, this.gl.FLOAT, false, 0, 0);
    this.gl.enableVertexAttribArray(vColor);

    // arrange cube vertex data stuff
    var vBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vBuffer);
    this.gl.bufferData(
      this.gl.ARRAY_BUFFER,
      flatten(this.pointsArray),
      this.gl.STATIC_DRAW
    );
    var vPosition = this.gl.getAttribLocation(this.program, "vPosition");
    this.gl.vertexAttribPointer(vPosition, 4, this.gl.FLOAT, false, 0, 0);
    this.gl.enableVertexAttribArray(vPosition);
  }
}

window.onload = function init() {
  //// initialize WebGl System
  const canvas = document.getElementById("gl-canvas");
  const gl = WebGLUtils.setupWebGL(canvas);
  if (!gl) {
    alert("WebGL isn't available");
  }
  gl.viewport(0, 0, canvas.width, canvas.height);
  aspect = canvas.width / canvas.height;
  gl.clearColor(1.0, 1.0, 1.0, 1.0);
  gl.enable(gl.DEPTH_TEST);

  //// Initialize game objects
  var cube1 = new Cube(gl, vec4(1.0, 0.0, 0.0, 1.0));
  var ground = new Cube(gl, vec4(0.0, 1.0, 0.0, 1.0));
  let gameObjects = [cube1];

  // sliders for viewing parameters
  readGUI();

  render(gl, gameObjects);
};

////
var render = function(gl, gameObjects) {
  //// clear the background
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  //// camera settings
  eye = vec3(
    radius * Math.sin(theta) * Math.cos(phi),
    radius * Math.sin(theta) * Math.sin(phi),
    radius * Math.cos(theta)
  );
  modelViewMatrix = lookAt(eye, at, up);
  projectionMatrix = perspective(fovy, aspect, near, far);

  //// draw all objects
  for (let objectI = 0; objectI < gameObjects.length; objectI++) {
    const gameObject = gameObjects[objectI];

    gl.useProgram(gameObject.program);

    gl.uniformMatrix4fv(
      gameObject.modelViewMatrixLoc,
      false,
      flatten(modelViewMatrix)
    );
    gl.uniformMatrix4fv(
      gameObject.projectionMatrixLoc,
      false,
      flatten(projectionMatrix)
    );
    gameObject.draw();
  }

  requestAnimFrame(() => render(gl, gameObjects));
};
...

1 个答案:

答案 0 :(得分:1)

在WebGL 1.0 drawArrays中,使用当前由vertexAttribPointer指定并由enableVertexAttribArray启用的顶点。

使用属性存储缓冲区对象(this.cBufferthis.vBuffer)和属性索引(this.vColorthis.vPosition):

initAttributeBuffers() {
    // arrange cube color data stuff
    this.cBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cBuffer);
    this.gl.bufferData(
        this.gl.ARRAY_BUFFER,
        flatten(this.colorsArray),
        this.gl.STATIC_DRAW
    );
    this.vColor = this.gl.getAttribLocation(this.program, "vColor");

    // arrange cube vertex data stuff
    this.vBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vBuffer);
    this.gl.bufferData(
        this.gl.ARRAY_BUFFER,
        flatten(this.pointsArray),
        this.gl.STATIC_DRAW
    );
    this.vPosition = this.gl.getAttribLocation(this.program, "vPosition");
}

在绘制调用之前指定并启用通用顶点属性数据的数组:

draw() {
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cBuffer);
    this.gl.vertexAttribPointer(this.vColor, 4, this.gl.FLOAT, false, 0, 0);
    this.gl.enableVertexAttribArray(this.vColor);

    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vBuffer);
    this.gl.vertexAttribPointer(this.vPosition, 4, this.gl.FLOAT, false, 0, 0);
    this.gl.enableVertexAttribArray(this.vPosition);

    this.gl.drawArrays(this.gl.TRIANGLES, 0, this.numVertices);
}

在WebGL 2.0中(或通过使用扩展名OES_vertex_array_object),可以通过使用 WebGLVertexArrayObject s来简化。

顶点规范在顶点数组对象中声明:

initAttributeBuffers() {
    // create vertex array object
    this.vao = this.gl.createVertexArray();
    this.gl.bindVertexArray(this.vao);

    // arrange cube color data stuff
    var cBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, cBuffer);
    this.gl.bufferData(
        this.gl.ARRAY_BUFFER,
        flatten(this.colorsArray),
        this.gl.STATIC_DRAW
    );
    var vColor = this.gl.getAttribLocation(this.program, "vColor");
    this.gl.vertexAttribPointer(vColor, 4, this.gl.FLOAT, false, 0, 0);
    this.gl.enableVertexAttribArray(vColor);

    // arrange cube vertex data stuff
    var vBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vBuffer);
    this.gl.bufferData(
        this.gl.ARRAY_BUFFER,
        flatten(this.pointsArray),
        this.gl.STATIC_DRAW
    );
    var vPosition = this.gl.getAttribLocation(this.program, "vPosition");
    this.gl.vertexAttribPointer(vPosition, 4, this.gl.FLOAT, false, 0, 0);
    this.gl.enableVertexAttribArray(vPosition);
}

在绘制调用之前绑定顶点数组就足够了:

draw() {
    this.gl.bindVertexArray(this.vao);
    this.gl.drawArrays(this.gl.TRIANGLES, 0, this.numVertices);
}