我想做任何ANGLE_instanced_arrays,我阅读了MDN上的文档,我什么都不懂。好吧,我知道我可以制作图形2D和3D,如:examples但对我来说这些例子太先进了,而且很难理解所有代码。任何人都可以帮我一个例子吗?
这部分我理解文档官方:
ANGLE_instanced_arrays扩展是WebGL API的一部分,如果它们共享相同的顶点数据,原始计数和类型,则允许多次绘制相同的对象或类似对象的组。
答案 0 :(得分:0)
你可以不用ANGLE_instanced_arrays
画画吗?使用和不使用绘图之间的区别是
您调用另一个绘制函数并传递一个额外的参数来绘制多少个实例。 ext.drawArraysInstancedANGLE
或ext.drawElementsInstancedANGLE
代替普通ext.drawArrays
或ext.drawElements
您向顶点着色器添加一个或多个属性,每个实例绘制的值只会更改一次。换句话说,如果你正在绘制一个立方体,那么在绘制第一个立方体时,属性的值将是每个顶点的相同值,在绘制第二个立方体时是一个不同的值,在绘制第三个立方体时是第三个值。如果每个顶点的正常属性发生变化,则每个立方体/项目只会更改一次这些属性。
要添加的最明显的属性是每个立方体的额外位置,以便每个立方体可以将不同的位置添加到顶点位置,但是您可以为纯立方体颜色添加另一个属性或添加矩阵属性,以便您可以定向每个立方体完全独立或任何你想要的东西。
对于那些每个立方体只更改一次的属性,您可以通过调用ext.vertexAttribDivisorANGLE
将其顶点除数设置为1。 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>
这是一个使用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>