首页 > 解决方案 > 如何使用扩展 ANGLE_instanced_arrays 做一些事情?

问题描述

我想做任何 ANGLE_instanced_arrays,我阅读了 MDN 上的文档,但我什么都不懂。好吧,我知道我可以制作图形 2D 和 3D 之类的:示例,但对我来说,这些示例太高级了,很难理解所有代码。谁能帮我举个例子?

这部分我对文档官方的理解:

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

这是我读到的

标签: javascriptarrays

解决方案


没有你能画ANGLE_instanced_arrays吗?有图和无图的区别是

  1. 您调用不同的绘图函数并传递要绘制多少个实例的额外参数。ext.drawArraysInstancedANGLEext.drawElementsInstancedANGLE代替正常的ext.drawArraysext.drawElements

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

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

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

这是一个绘制单个四边形(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>

这是一个使用 . 绘制 100 个四边形的示例ANGLE_instanced_arrays。我们为每个四边形添加了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>


推荐阅读