如何使用扩展名ANGLE_instanced_arrays执行某些操作?

时间:2018-06-19 01:55:59

标签: javascript arrays

我想做任何ANGLE_instanced_arrays,我阅读了MDN上的文档,我什么都不懂。好吧,我知道我可以制作图形2D和3D,如:examples但对我来说这些例子太先进了,而且很难理解所有代码。任何人都可以帮我一个例子吗?

这部分我理解文档官方:

  

ANGLE_instanced_arrays扩展是WebGL API的一部分,如果它们共享相同的顶点数据,原始计数和类型,则允许多次绘制相同的对象或类似对象的组。

here is what I read

1 个答案:

答案 0 :(得分:0)

你可以不用ANGLE_instanced_arrays画画吗?使用和不使用绘图之间的区别是

  1. 您调用另一个绘制函数并传递一个额外的参数来绘制多少个实例。 ext.drawArraysInstancedANGLEext.drawElementsInstancedANGLE代替普通ext.drawArraysext.drawElements

  2. 您向顶点着色器添加一个或多个属性,每个实例绘制的值只会更改一次。换句话说,如果你正在绘制一个立方体,那么在绘制第一个立方体时,属性的值将是每个顶点的相同值,在绘制第二个立方体时是一个不同的值,在绘制第三个立方体时是第三个值。如果每个顶点的正常属性发生变化,则每个立方体/项目只会更改一次这些属性。

    要添加的最明显的属性是每个立方体的额外位置,以便每个立方体可以将不同的位置添加到顶点位置,但是您可以为纯立方体颜色添加另一个属性或添加矩阵属性,以便您可以定向每个立方体完全独立或任何你想要的东西。

  3. 对于那些每个立方体只更改一次的属性,您可以通过调用ext.vertexAttribDivisorANGLE将其顶点除数设置为1。 1表示“每1个实例推进属性”。 0(默认值)表示advance the attribute every vertex (every iteration of the vertex shader)

  4. 这是绘制单个四边形(2个三角形,6个顶点)

    的示例

    const vs = `
    attribute vec4 position;
    uniform mat4 u_matrix;
    
    void main() {
      gl_Position = u_matrix * position;
    }
    `;
    
    const fs = `
    precision mediump float;
    
    uniform vec4 u_color;
    void main() {
      gl_FragColor = u_color;
    }
    `;
    
    const m4 = twgl.m4;
    const gl = document.querySelector("canvas").getContext("webgl");
    const program = twgl.createProgram(gl, [vs, fs]);
    
    const positionLocation = gl.getAttribLocation(program, "position");
    
    const matrixLocation = gl.getUniformLocation(program, "u_matrix");
    const colorLocation = gl.getUniformLocation(program, "u_color");
    
    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
       // one face
        -1, -1, 
         1, -1,
        -1,  1,
        -1,  1,
         1, -1,
         1,  1,
      ],
    ), gl.STATIC_DRAW);
    
    gl.enable(gl.DEPTH_TEST);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.enableVertexAttribArray(positionLocation);
    {
      const size = 2;  // 2 values per vertex
      const type = gl.FLOAT;
      const normalize = false;
      const stride = 0;
      const offset = 0;
      gl.vertexAttribPointer(positionLocation, size, type, normalize, stride, offset);
    }
    
    gl.useProgram(program);
    gl.uniform4fv(colorLocation, [1, .5, .2, 1]);
    gl.uniformMatrix4fv(matrixLocation, false, m4.scaling([.25, .25, .25]));
    const offset = 0;
    const vertexCount = 6;
    gl.drawArrays(gl.TRIANGLES, offset, vertexCount);
    canvas { border: 1px solid black; }
    <script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
    <canvas></canvas>

    这是一个使用ANGLE_instanced_arrays绘制100个四边形的示例。我们为每个四元组添加了planeOffset的偏移量,为每个四元组添加了planeColor颜色。

    const vs = `
    attribute vec4 position;
    attribute vec2 planeOffset;    // per plane offset
    attribute vec4 planeColor;     // per plane color
    uniform mat4 u_matrix;
    varying vec4 v_color;
    void main() {
      mat4 translation = mat4(
        vec4(1, 0, 0, 0),
        vec4(0, 1, 0, 0),
        vec4(0, 0, 1, 0),
        vec4(planeOffset, 0, 1));
      gl_Position = u_matrix * translation * position;
      v_color = planeColor;
    }
    `;
    
    const fs = `
    precision mediump float;
    varying vec4 v_color;
    void main() {
      gl_FragColor = v_color;
    }
    `;
    
    function main() {
      const m4 = twgl.m4;
      const gl = document.querySelector("canvas").getContext("webgl");
      const ext = gl.getExtension("ANGLE_instanced_arrays");
      if (!ext) {
        alert("need ANGLE_instanced_arrays");
        return;
      }
      
      const program = twgl.createProgram(gl, [vs, fs]);
    
      const positionLocation = gl.getAttribLocation(program, "position");
      const offsetLocation = gl.getAttribLocation(program, "planeOffset");
      const colorLocation = gl.getAttribLocation(program, "planeColor");
    
      const matrixLocation = gl.getUniformLocation(program, "u_matrix");
    
      const positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
         // one face
          -1, -1, 
           1, -1,
          -1,  1,
          -1,  1,
           1, -1,
           1,  1,
        ],
      ), gl.STATIC_DRAW);
      
      // make 100 offsets and 100 colors
      const colors = [];
      const offsets = [];
      const numInstances = 100;
      for (let i = 0; i < 100; ++i) {
        colors.push(Math.random(), Math.random(), Math.random(), 1);
        offsets.push(Math.random() * 20 - 10, Math.random() * 20 - 10);
      }
      
      // put those in buffers
      const offsetBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(offsets), gl.STATIC_DRAW);  
      
      const colorBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);  
    
      gl.enable(gl.DEPTH_TEST);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.enableVertexAttribArray(positionLocation);
      {
        const size = 2;  // 2 values per vertex
        const type = gl.FLOAT;
        const normalize = false;
        const stride = 0;
        const offset = 0;
        gl.vertexAttribPointer(positionLocation, size, type, normalize, stride, offset);
      }
      
      gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
      gl.enableVertexAttribArray(offsetLocation);
      {
        const size = 2;  // 2 values per vertex
        const type = gl.FLOAT;
        const normalize = false;
        const stride = 0;
        const offset = 0;
        gl.vertexAttribPointer(offsetLocation, size, type, normalize, stride, offset);
        ext.vertexAttribDivisorANGLE(offsetLocation, 1);
      }
    
      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
      gl.enableVertexAttribArray(colorLocation);
      {
        const size = 4;  // 4 values per vertex
        const type = gl.FLOAT;
        const normalize = false;
        const stride = 0;
        const offset = 0;
        gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);
        ext.vertexAttribDivisorANGLE(colorLocation, 1);
      }
      
      gl.useProgram(program);
      gl.uniformMatrix4fv(matrixLocation, false, m4.scaling([.1, .1, .1]));
      const offset = 0;
      const vertexCount = 6;  
      ext.drawArraysInstancedANGLE(gl.TRIANGLES, offset, vertexCount, numInstances);
    }
    main();
    canvas { border: 1px solid black; }
    <script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
    <canvas></canvas>