【问题标题】:What am I doing wrong in the following WebGL code?我在以下 WebGL 代码中做错了什么?
【发布时间】:2019-12-01 04:57:18
【问题描述】:

我从一个在页面上显示单个立方体的示例 WebGL 程序开始。示例代码不使用类。

我希望能够绘制多个可以独立移动的立方体。所以我添加了一个“Cube”类。此类的每个实例都使用自己的“程序”。我创建了两个对象,但我只画了第一个。不幸的是,后来实例化的对象被显示出来。例如。在下面的代码中显示的是“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));
};
...

【问题讨论】:

    标签: webgl


    【解决方案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),可以通过使用 WebGLVertexArrayObjects 来简化。

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

    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 call之前绑定顶点数组就足够了:

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

    【讨论】:

      猜你喜欢
      • 2021-03-20
      • 2013-10-18
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多