WebGL入门(045):ANGLE_instanced_arrays 简介、使用方法、示例代码
WebGL 是一门强大的技术,允许在浏览器中渲染 2D 和 3D 图形。在 WebGL 中,我们通常需要绘制大量的对象,例如粒子系统,或者大规模的场景元素。为了提高性能,WebGL 允许使用一个名为 ANGLE_instanced_arrays 的扩展,这个扩展提供了一种批量绘制的方式,使我们可以更方便地处理实例化几何体。
1. ANGLE_instanced_arrays 概述
ANGLE_instanced_arrays 扩展允许我们在一个绘制调用中渲染多个几何实例。通过这种方式,我们不仅能够减少 CPU 与 GPU 之间的通信次数,还能提高渲染效率,对于大量相似对象的渲染尤其有效。
在使用该扩展时,我们通常使用以下几个主要的函数:
vertexAttribDivisor(index, divisor)
:设置顶点属性的分配因子,指定该属性在实例间的变化频率。drawArraysInstanced(mode, first, count, instanceCount)
:基于数组绘制实例化的几何体。drawElementsInstanced(mode, count, type, offset, instanceCount)
:基于元素数组绘制实例化的几何体。
2. 使用方法
在使用 ANGLE_instanced_arrays 扩展之前,我们需要先检查是否支持这个扩展。以下是一个简单的使用步骤:
- 获取 WebGL 上下文并检查扩展。
- 创建用于实例化的缓冲区。
- 定义顶点着色器和片元着色器。
- 设置顶点属性和实例属性。
- 使用实例化绘制函数进行渲染。
3. 示例代码
下面是一个使用 ANGLE_instanced_arrays 的简单示例,绘制多个实例化的三角形。
// 初始化 WebGL 上下文
const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");
if (!gl.getExtension('ANGLE_instanced_arrays')) {
console.error('ANGLE_instanced_arrays not supported');
}
// 顶点着色器
const vsSource = `
attribute vec4 a_position;
attribute vec4 a_offset;
void main() {
gl_Position = a_position + a_offset;
}
`;
// 片元着色器
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
`;
// 编译着色器的辅助函数
function compileShader(gl, source, type) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader;
} else {
console.error(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
}
// 创建程序
const vertexShader = compileShader(gl, vsSource, gl.VERTEX_SHADER);
const fragmentShader = compileShader(gl, fsSource, gl.FRAGMENT_SHADER);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 定义三角形的顶点
const positions = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5,
]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
// 实例偏移数据
const offsets = new Float32Array([
0.0, 0.0,
0.5, 0.0,
-0.5, 0.0,
0.0, 0.5,
]);
const offsetBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
// 绑定位置属性
const positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// 绑定偏移属性
const offsetLocation = gl.getAttribLocation(program, "a_offset");
gl.enableVertexAttribArray(offsetLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
gl.vertexAttribPointer(offsetLocation, 2, gl.FLOAT, false, 0, 0);
gl.vertexAttribDivisor(offsetLocation, 1); // 设置为每个实例变化
// 进行绘制
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 4); // 绘制 4 个实例
4. 总结
ANGLE_instanced_arrays 扩展为 WebGL 提供了一种高效的实例化渲染方式,通过合理利用实例化,可以极大地提高渲染性能,尤其是在有大量相似对象的场景中。了解并掌握这一扩展的使用,对于提升 WebGL 绘图性能和流畅度至关重要。希望本文能够帮助你理解 ANGLE_instanced_arrays 的基本概念及其应用方法。