bufferData
是 WebGL2 中用于初始化或更新缓冲区对象数据存储的核心方法,它是处理顶点属性、索引和其他缓冲区类型的基础操作。
基本语法
ini
gl.bufferData(target, size, usage);
gl.bufferData(target, data, usage);
gl.bufferData(target, srcData, usage, srcOffset, length);
参数说明
-
target - 指定缓冲区绑定目标:
gl.ARRAY_BUFFER
:顶点属性数据gl.ELEMENT_ARRAY_BUFFER
:索引数据gl.COPY_READ_BUFFER
/gl.COPY_WRITE_BUFFER
:复制操作缓冲区gl.TRANSFORM_FEEDBACK_BUFFER
:变换反馈缓冲区gl.UNIFORM_BUFFER
:统一变量缓冲区
-
size/data/srcData:
- 可以是指定缓冲区大小的数字
- 或者是包含数据的
ArrayBuffer
、TypedArray
、DataView
对象 - WebGL2 新增支持指定源数据的偏移和长度
-
usage - 指定数据使用模式:
gl.STATIC_DRAW
:数据内容很少更改gl.DYNAMIC_DRAW
:数据内容会频繁更改gl.STREAM_DRAW
:数据内容每次绘制都会更改- WebGL2 新增:
gl.STATIC_READ
、gl.DYNAMIC_READ
、gl.STREAM_READ
等
WebGL2 新增特性
- 支持更多缓冲区类型(如统一变量缓冲区)
- 可以指定数据源的偏移和长度
- 增加了更多 usage 模式
- 支持使用
gl.bufferSubData
进行部分更新
使用示例
以下是一个完整的可直接运行的示例:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL2 三角形渲染示例</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; width: 600px; height: 400px; }
</style>
</head>
<body>
<canvas id="glCanvas"></canvas>
<script>
// 顶点着色器代码
const vertexShaderSource = `#version 300 es
in vec2 aPosition;
in vec3 aColor;
out vec3 vColor;
void main() {
gl_Position = vec4(aPosition, 0.0, 1.0);
vColor = aColor;
}`;
// 片段着色器代码
const fragmentShaderSource = `#version 300 es
precision highp float;
in vec3 vColor;
out vec4 fragColor;
void main() {
fragColor = vec4(vColor, 1.0);
}`;
// 初始化WebGL2上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl2');
if (!gl) {
alert('您的浏览器不支持WebGL2');
throw new Error('WebGL2 not supported');
}
// 编译着色器
function compileShader(source, type) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('着色器编译错误:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
// 创建着色器程序
const vertexShader = compileShader(vertexShaderSource, gl.VERTEX_SHADER);
const fragmentShader = compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER);
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('着色器程序链接错误:', gl.getProgramInfoLog(shaderProgram));
}
// 定义顶点数据 (位置和颜色)
const vertices = new Float32Array([
// 位置 (x, y) 颜色 (r, g, b)
-0.5, -0.5, 1.0, 0.0, 0.0, // 左下 - 红色
0.5, -0.5, 0.0, 1.0, 0.0, // 右下 - 绿色
0.0, 0.5, 0.0, 0.0, 1.0 // 顶部 - 蓝色
]);
// 定义索引数据
const indices = new Uint16Array([
0, 1, 2 // 组成三角形的三个顶点索引
]);
// 创建并绑定顶点缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 创建并绑定索引缓冲区
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
// 获取着色器中的属性位置
const positionAttributeLocation = gl.getAttribLocation(shaderProgram, "aPosition");
const colorAttributeLocation = gl.getAttribLocation(shaderProgram, "aColor");
// 启用并设置顶点属性指针
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(
positionAttributeLocation,
2, // 每个顶点位置有2个分量 (x, y)
gl.FLOAT, // 数据类型
false, // 是否归一化
5 * 4, // 步长 (5个浮点数,每个4字节)
0 // 偏移量
);
gl.enableVertexAttribArray(colorAttributeLocation);
gl.vertexAttribPointer(
colorAttributeLocation,
3, // 每个顶点颜色有3个分量 (r, g, b)
gl.FLOAT, // 数据类型
false, // 是否归一化
5 * 4, // 步长 (5个浮点数,每个4字节)
2 * 4 // 偏移量 (跳过前2个浮点数)
);
// 清除画布
gl.clearColor(0.1, 0.1, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// 使用着色器程序
gl.useProgram(shaderProgram);
// 绘制三角形
gl.drawElements(
gl.TRIANGLES, // 绘制模式
indices.length, // 顶点数量
gl.UNSIGNED_SHORT, // 索引数据类型
0 // 偏移量
);
</script>
</body>
</html>
注意事项
- 必须先绑定缓冲区才能调用 bufferData
- 选择正确的 usage 可以提高性能
- 大型缓冲区应考虑使用 gl.bufferStorage (WebGL2 新增)
- 数据格式必须与着色器中声明的属性类型匹配