HTML5 canvas webgl,无法绘制立方体

HTML5 canvas webgl, cant get a cube to be drawn

我正在尝试制作一个程序,使用 js 和 webgl 在 html5 canvas 的屏幕上绘制立方体。我想做到这一点,这样我就可以在我做 webgl.makeCupe() 时制作一个新的多维数据集,有点像 canvasRendering2D.fillRect 的工作方式,但由于某种原因不起作用,我知道 webgl 可以工作,因为它为背景着色,我没有收到任何错误,但立方体上没有绘制任何东西(背景旁边)

let ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
 
 function create() {
  let out = new ARRAY_TYPE(16);
  if(ARRAY_TYPE != Float32Array) {
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[11] = 0;
    out[12] = 0;
    out[13] = 0;
    out[14] = 0;
  }
  out[0] = 1;
  out[5] = 1;
  out[10] = 1;
  out[15] = 1;
  return out;
}

function perspective(out, fovy, aspect, near, far) {
  let f = 1.0 / Math.tan(fovy / 2), nf;
  out[0] = f / aspect;
  out[1] = 0;
  out[2] = 0;
  out[3] = 0;
  out[4] = 0;
  out[5] = f;
  out[6] = 0;
  out[7] = 0;
  out[8] = 0;
  out[9] = 0;
  out[11] = -1;
  out[12] = 0;
  out[13] = 0;
  out[15] = 0;
  if (far !== null && far !== Infinity) {
    nf = 1 / (near - far);
    out[10] = (far + near) * nf;
    out[14] = (2 * far * near) * nf;
  } else {
    out[10] = -1;
    out[14] = -2 * near;
  }
  return out;
}

 function translate(out, a, v) {
  let x = v[0], y = v[1], z = v[2];
  let a00, a01, a02, a03;
  let a10, a11, a12, a13;
  let a20, a21, a22, a23;

  if (a === out) {
    out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
    out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
    out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
    out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  } else {
    a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
    a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
    a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];

    out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
    out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
    out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;

    out[12] = a00 * x + a10 * y + a20 * z + a[12];
    out[13] = a01 * x + a11 * y + a21 * z + a[13];
    out[14] = a02 * x + a12 * y + a22 * z + a[14];
    out[15] = a03 * x + a13 * y + a23 * z + a[15];
  }

  return out;
}
//shaders

const shaders = {
  vertex: `
    precision mediump float;
    
    attribute vec4 avertPosition;
    attribute vec4 avertColor;
    
    varying vec4 vfragColor;
    
    uniform mat4 umodelMatrix;
    uniform mat4 uprojectionMatrix;
    
    void main()
    {
      vfragColor = avertColor;
      gl_Position  =  uprojectionMatrix * umodelMatrix * avertPosition;
    }
    `,
  fragment:
    `
    precision mediump float;
    
    varying vec4 vfragColor;
    void main()
    {
      gl_FragColor = vfragColor;
    }
    `
};

//cube class

class Cube {
  constructor(gl){
    
    this.gl = gl;
    
    this.buffers;
    
   
    
  }
  setUp(){

    const positionBuffer = this.gl.createBuffer();
  
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);
  
  
    const positions = [
      // Front face
      -1.0, -1.0,  1.0,
       1.0, -1.0,  1.0,
       1.0,  1.0,  1.0,
      -1.0,  1.0,  1.0,
  
      // Back face
      -1.0, -1.0, -1.0,
      -1.0,  1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0, -1.0, -1.0,
  
      // Top face
      -1.0,  1.0, -1.0,
      -1.0,  1.0,  1.0,
       1.0,  1.0,  1.0,
       1.0,  1.0, -1.0,
  
      // Bottom face
      -1.0, -1.0, -1.0,
       1.0, -1.0, -1.0,
       1.0, -1.0,  1.0,
      -1.0, -1.0,  1.0,
  
      // Right face
       1.0, -1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0,  1.0,  1.0,
       1.0, -1.0,  1.0,
  
      // Left face
      -1.0, -1.0, -1.0,
      -1.0, -1.0,  1.0,
      -1.0,  1.0,  1.0,
      -1.0,  1.0, -1.0,
    ];
  
    this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(positions), this.gl.STATIC_DRAW);

    const faceColors = [
      [1.0,  1.0,  1.0,  1.0],
      [1.0,  0.0,  0.0,  1.0],
      [0.0,  1.0,  0.0,  1.0],
      [0.0,  0.0,  1.0,  1.0],
      [1.0,  1.0,  0.0,  1.0],
      [1.0,  0.0,  1.0,  1.0],
    ];
  
  
    var colors = [];
  
    for (var j = 0; j < faceColors.length; ++j) {
      const c = faceColors[j];
  
      colors = colors.concat(c, c, c, c);
    }
  
    const colorBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, colorBuffer);
    this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(colors), this.gl.STATIC_DRAW);
  
  
    const indices = [
      0,  1,  2,      0,  2,  3,    // front
      4,  5,  6,      4,  6,  7,    // back
      8,  9,  10,     8,  10, 11,   // top
      12, 13, 14,     12, 14, 15,   // bottom
      16, 17, 18,     16, 18, 19,   // right
      20, 21, 22,     20, 22, 23,   // left
    ];
  
  
    const indexBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  
    this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER,
      new Uint16Array(indices), this.gl.STATIC_DRAW);
      
    this.buffers = {
      position: positionBuffer,
      color: colorBuffer,
      indices: indexBuffer,
    };
    
  }
}

//webgl class

class WebglProgram {
 constructor(canvas){
  
  this.gl = canvas.getContext("webgl");
  
  this.program;
  
  this.shaders = {};
  
  this.cubes = [];
  
 }
 
 async setUp(){
  
  if (!this.gl) {
   log('WebGL not supported, falling back on experimental-webgl');
   this.gl = canvas.getContext('experimental-webgl');
  }
  
  if (!this.gl) {
   log('Your browser does not support WebGL');
   return null;
  }
  
  let vertexShader  = this.gl.createShader(this.gl.VERTEX_SHADER);
  let fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
  
  this.gl.shaderSource(vertexShader, shaders.vertex);
  this.gl.shaderSource(fragmentShader, shaders.fragment);
  
  
  this.program = this.gl.createProgram();
  
  
  [vertexShader, fragmentShader].forEach(shader => {
  
   this.gl.compileShader(shader);
  
   if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
    error(`ERROR compiling a shader!`, this.gl.getShaderInfoLog(shader));
    this.gl.deleteShader(shader);
    return;
   }
   
   this.gl.attachShader(this.program, shader);
  
  });
  
  this.gl.linkProgram(this.program);
  
  
  if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {
   error('ERROR linking program!', this.gl.getProgramInfoLog(this.program));
   return;
  }
  
  //Delete later since its extisnisve
  
  this.gl.validateProgram(this.program);
  if (!this.gl.getProgramParameter(this.program, this.gl.VALIDATE_STATUS)) {
   error('ERROR validating program!', this.gl.getProgramInfoLog(this.program));
   return;
  }
  
  
  this.shaders.attributes = {
    positionAttrib : this.gl.getAttribLocation(this.program, 'avertPosition'),
    colorAttrib   : this.gl.getAttribLocation(this.program, 'avertColor'),
  };
  
  this.shaders.uniforms = {
    modelMatrix      : this.gl.getUniformLocation(this.program, 'umodelMatrix'),
    projectionMatrix : this.gl.getUniformLocation(this.program, 'uprojectionMatrix'),
  };
  
  return "Webgl Set Up";
 }
 
 clear(color){
  
  this.gl.clearColor(color[0], color[1], color[2], color[3]);
  this.gl.clearDepth(1);
  
  this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);

  
  return "Cleared";
 }
 
 makeCube(){

  let newCube = new Cube(this.gl);
    
    newCube.setUp();
  
  this.cubes.push(newCube);
  
  return "FillRect called";
  
 }
 
 render(){
  for (let i = 0; i < this.cubes.length; i++) {

   
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubes[i].buffers.positionBuffer);
   this.gl.vertexAttribPointer(
     this.shaders.attributes.positionAttrib,
     3,
     this.gl.FLOAT,
     this.gl.FALSE,
     0 * Float32Array.BYTES_PER_ELEMENT,
     0 * Float32Array.BYTES_PER_ELEMENT
   );
  
   this.gl.enableVertexAttribArray(this.shaders.attributes.positionAttrib);
   

   
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubes[i].buffers.colorBuffer);
   this.gl.vertexAttribPointer(
     this.shaders.attributes.colorAttrib,
     4,
     this.gl.FLOAT,
     this.gl.FALSE,
     0 * Float32Array.BYTES_PER_ELEMENT,
     0 * Float32Array.BYTES_PER_ELEMENT
   );
  
   this.gl.enableVertexAttribArray(this.shaders.attributes.colorAttrib);
   
   
   this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.cubes[i].buffers.indices);
    
   this.gl.useProgram(this.program);
   
      const projectionMatrix = create();
      const modelMatrix  = create();
      
      
      const fieldOfView = 45 * Math.PI / 180;
      const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight;
      const zNear = 0.1;
      const zFar = 100.0;

  
      perspective(projectionMatrix,
                   fieldOfView,
                   aspect,
                   zNear,
                   zFar);
                   
      translate(modelMatrix,
        modelMatrix,
        [0.0, 0.0, -6.0]
        );
      

      this.gl.uniformMatrix4fv(
          this.shaders.uniforms.projectionMatrix,
          false,
          projectionMatrix);
          
      this.gl.uniformMatrix4fv(
          this.shaders.uniforms.modelMatrix,
          false,
          modelMatrix);
          
      this.gl.drawElements(this.gl.TRIANGLES, 36, this.gl.UNSIGNED_SHORT, 0);
      
          
  }
 }
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>repl.it</title>
    <link href="style.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <canvas id = "webglCanvas"></canvas>
    <script>
      onload = function(){

        let canvas = document.querySelector("#webglCanvas")

        let webgl = new WebglProgram(canvas)

        canvas.width = 500;
        canvas.height = 500;

        webgl.setUp()

        .then(()=>{
          webgl.gl.viewport(0, 0, 500, 500);
          webgl.makeCube()
          loop(webgl)
        })
      }

      function loop(webgl){
        function draw(){
          webgl.clear([1, 1, 0, 1])
          
          webgl.render()

          requestAnimationFrame(draw)

        }
        requestAnimationFrame(draw)
      }

    </script>
  </body>
</html>

WebGLRenderingContext{}是html动画中的常见问题。如果您收到错误消息“WebGL 已禁用”,则可能是:

  • 您可能需要关闭浏览器并强制重启计算机
  • 您的浏览器需要更新
  • 您的浏览器禁用了 WebGL 和硬件加速
  • 浏览器plug-in禁用了 WebGL
  • IT 组织已在您的计算机上禁用 WebGL
  • 您的机器硬件不支持 WebGL

你应该做的第一件事是检查 the JavaScript console

您发布的代码显示错误,您应该尝试修复该错误

看到上面的错误是关于没有绑定缓冲区我查看了它绑定缓冲区的代码。我在那里放了一个断点 in the debugger

检查我看到你使用的值 positionBuffercolorBuffer 但它们被称为 positioncolor

修复那些被绘制的东西。

let ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;

function create() {
  let out = new ARRAY_TYPE(16);
  if (ARRAY_TYPE != Float32Array) {
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[11] = 0;
    out[12] = 0;
    out[13] = 0;
    out[14] = 0;
  }
  out[0] = 1;
  out[5] = 1;
  out[10] = 1;
  out[15] = 1;
  return out;
}

function perspective(out, fovy, aspect, near, far) {
  let f = 1.0 / Math.tan(fovy / 2),
    nf;
  out[0] = f / aspect;
  out[1] = 0;
  out[2] = 0;
  out[3] = 0;
  out[4] = 0;
  out[5] = f;
  out[6] = 0;
  out[7] = 0;
  out[8] = 0;
  out[9] = 0;
  out[11] = -1;
  out[12] = 0;
  out[13] = 0;
  out[15] = 0;
  if (far !== null && far !== Infinity) {
    nf = 1 / (near - far);
    out[10] = (far + near) * nf;
    out[14] = (2 * far * near) * nf;
  } else {
    out[10] = -1;
    out[14] = -2 * near;
  }
  return out;
}

function translate(out, a, v) {
  let x = v[0],
    y = v[1],
    z = v[2];
  let a00, a01, a02, a03;
  let a10, a11, a12, a13;
  let a20, a21, a22, a23;

  if (a === out) {
    out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
    out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
    out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
    out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  } else {
    a00 = a[0];
    a01 = a[1];
    a02 = a[2];
    a03 = a[3];
    a10 = a[4];
    a11 = a[5];
    a12 = a[6];
    a13 = a[7];
    a20 = a[8];
    a21 = a[9];
    a22 = a[10];
    a23 = a[11];

    out[0] = a00;
    out[1] = a01;
    out[2] = a02;
    out[3] = a03;
    out[4] = a10;
    out[5] = a11;
    out[6] = a12;
    out[7] = a13;
    out[8] = a20;
    out[9] = a21;
    out[10] = a22;
    out[11] = a23;

    out[12] = a00 * x + a10 * y + a20 * z + a[12];
    out[13] = a01 * x + a11 * y + a21 * z + a[13];
    out[14] = a02 * x + a12 * y + a22 * z + a[14];
    out[15] = a03 * x + a13 * y + a23 * z + a[15];
  }

  return out;
}
//shaders

const shaders = {
  vertex: `
    precision mediump float;
    
    attribute vec4 avertPosition;
    attribute vec4 avertColor;
    
    varying vec4 vfragColor;
    
    uniform mat4 umodelMatrix;
    uniform mat4 uprojectionMatrix;
    
    void main()
    {
      vfragColor = avertColor;
      gl_Position  =  uprojectionMatrix * umodelMatrix * avertPosition;
    }
    `,
  fragment: `
    precision mediump float;
    
    varying vec4 vfragColor;
    void main()
    {
      gl_FragColor = vfragColor;
    }
    `
};

//cube class

class Cube {
  constructor(gl) {

    this.gl = gl;

    this.buffers;



  }
  setUp() {

    const positionBuffer = this.gl.createBuffer();

    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);


    const positions = [
      // Front face
      -1.0, -1.0, 1.0,
      1.0, -1.0, 1.0,
      1.0, 1.0, 1.0, -1.0, 1.0, 1.0,

      // Back face
      -1.0, -1.0, -1.0, -1.0, 1.0, -1.0,
      1.0, 1.0, -1.0,
      1.0, -1.0, -1.0,

      // Top face
      -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,
      1.0, 1.0, 1.0,
      1.0, 1.0, -1.0,

      // Bottom face
      -1.0, -1.0, -1.0,
      1.0, -1.0, -1.0,
      1.0, -1.0, 1.0, -1.0, -1.0, 1.0,

      // Right face
      1.0, -1.0, -1.0,
      1.0, 1.0, -1.0,
      1.0, 1.0, 1.0,
      1.0, -1.0, 1.0,

      // Left face
      -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
    ];

    this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(positions), this.gl.STATIC_DRAW);

    const faceColors = [
      [1.0, 1.0, 1.0, 1.0],
      [1.0, 0.0, 0.0, 1.0],
      [0.0, 1.0, 0.0, 1.0],
      [0.0, 0.0, 1.0, 1.0],
      [1.0, 1.0, 0.0, 1.0],
      [1.0, 0.0, 1.0, 1.0],
    ];


    var colors = [];

    for (var j = 0; j < faceColors.length; ++j) {
      const c = faceColors[j];

      colors = colors.concat(c, c, c, c);
    }

    const colorBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, colorBuffer);
    this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(colors), this.gl.STATIC_DRAW);


    const indices = [
      0, 1, 2, 0, 2, 3, // front
      4, 5, 6, 4, 6, 7, // back
      8, 9, 10, 8, 10, 11, // top
      12, 13, 14, 12, 14, 15, // bottom
      16, 17, 18, 16, 18, 19, // right
      20, 21, 22, 20, 22, 23, // left
    ];


    const indexBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

    this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER,
      new Uint16Array(indices), this.gl.STATIC_DRAW);

    this.buffers = {
      position: positionBuffer,
      color: colorBuffer,
      indices: indexBuffer,
    };

  }
}

//webgl class

class WebglProgram {
  constructor(canvas) {

    this.gl = canvas.getContext("webgl");

    this.program;

    this.shaders = {};

    this.cubes = [];

  }

  async setUp() {

    if (!this.gl) {
      log('WebGL not supported, falling back on experimental-webgl');
      this.gl = canvas.getContext('experimental-webgl');
    }

    if (!this.gl) {
      log('Your browser does not support WebGL');
      return null;
    }

    let vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
    let fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);

    this.gl.shaderSource(vertexShader, shaders.vertex);
    this.gl.shaderSource(fragmentShader, shaders.fragment);


    this.program = this.gl.createProgram();


    [vertexShader, fragmentShader].forEach(shader => {

      this.gl.compileShader(shader);

      if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
        error(`ERROR compiling a shader!`, this.gl.getShaderInfoLog(shader));
        this.gl.deleteShader(shader);
        return;
      }

      this.gl.attachShader(this.program, shader);

    });

    this.gl.linkProgram(this.program);


    if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {
      error('ERROR linking program!', this.gl.getProgramInfoLog(this.program));
      return;
    }

    //Delete later since its extisnisve

    this.gl.validateProgram(this.program);
    if (!this.gl.getProgramParameter(this.program, this.gl.VALIDATE_STATUS)) {
      error('ERROR validating program!', this.gl.getProgramInfoLog(this.program));
      return;
    }


    this.shaders.attributes = {
      positionAttrib: this.gl.getAttribLocation(this.program, 'avertPosition'),
      colorAttrib: this.gl.getAttribLocation(this.program, 'avertColor'),
    };

    this.shaders.uniforms = {
      modelMatrix: this.gl.getUniformLocation(this.program, 'umodelMatrix'),
      projectionMatrix: this.gl.getUniformLocation(this.program, 'uprojectionMatrix'),
    };

    return "Webgl Set Up";
  }

  clear(color) {

    this.gl.clearColor(color[0], color[1], color[2], color[3]);
    this.gl.clearDepth(1);

    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);


    return "Cleared";
  }

  makeCube() {

    let newCube = new Cube(this.gl);

    newCube.setUp();

    this.cubes.push(newCube);

    return "FillRect called";

  }

  render() {
    for (let i = 0; i < this.cubes.length; i++) {


      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubes[i].buffers.position);
      this.gl.vertexAttribPointer(
        this.shaders.attributes.positionAttrib,
        3,
        this.gl.FLOAT,
        this.gl.FALSE,
        0 * Float32Array.BYTES_PER_ELEMENT,
        0 * Float32Array.BYTES_PER_ELEMENT
      );

      this.gl.enableVertexAttribArray(this.shaders.attributes.positionAttrib);



      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubes[i].buffers.color);
      this.gl.vertexAttribPointer(
        this.shaders.attributes.colorAttrib,
        4,
        this.gl.FLOAT,
        this.gl.FALSE,
        0 * Float32Array.BYTES_PER_ELEMENT,
        0 * Float32Array.BYTES_PER_ELEMENT
      );

      this.gl.enableVertexAttribArray(this.shaders.attributes.colorAttrib);


      this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.cubes[i].buffers.indices);

      this.gl.useProgram(this.program);

      const projectionMatrix = create();
      const modelMatrix = create();


      const fieldOfView = 45 * Math.PI / 180;
      const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight;
      const zNear = 0.1;
      const zFar = 100.0;


      perspective(projectionMatrix,
        fieldOfView,
        aspect,
        zNear,
        zFar);

      translate(modelMatrix,
        modelMatrix, [0.0, 0.0, -6.0]
      );


      this.gl.uniformMatrix4fv(
        this.shaders.uniforms.projectionMatrix,
        false,
        projectionMatrix);

      this.gl.uniformMatrix4fv(
        this.shaders.uniforms.modelMatrix,
        false,
        modelMatrix);

      this.gl.drawElements(this.gl.TRIANGLES, 36, this.gl.UNSIGNED_SHORT, 0);


    }
  }
}

function main() {

  let canvas = document.querySelector("#webglCanvas")

  let webgl = new WebglProgram(canvas)

  canvas.width = 500;
  canvas.height = 500;

  webgl.setUp()

    .then(() => {
      webgl.gl.viewport(0, 0, 500, 500);
      webgl.makeCube()
      loop(webgl)
    })
}

function loop(webgl) {
  function draw() {
    webgl.clear([1, 1, 0, 1])

    webgl.render()

    requestAnimationFrame(draw)

  }
  requestAnimationFrame(draw)
}

main();
<canvas id="webglCanvas"></canvas>

请注意,您可以使用 webgl debug context 捕获这些类型的错误。它是一个包装 WebGL 并检查错误的库。上面的 link 还展示了如何检查是否通过 undefined,这是当出现像上面这样的错字时会发生的情况。

另外查看 these tutorials

以防万一