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 扩展之前,我们需要先检查是否支持这个扩展。以下是一个简单的使用步骤:

  1. 获取 WebGL 上下文并检查扩展。
  2. 创建用于实例化的缓冲区。
  3. 定义顶点着色器和片元着色器。
  4. 设置顶点属性和实例属性。
  5. 使用实例化绘制函数进行渲染。

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 的基本概念及其应用方法。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部