webgl2 方法解析: bufferData()

bufferData 是 WebGL2 中用于初始化或更新缓冲区对象数据存储的核心方法,它是处理顶点属性、索引和其他缓冲区类型的基础操作。

基本语法

ini 复制代码
gl.bufferData(target, size, usage);
gl.bufferData(target, data, usage);
gl.bufferData(target, srcData, usage, srcOffset, length);

参数说明

  1. target - 指定缓冲区绑定目标:

    • gl.ARRAY_BUFFER:顶点属性数据
    • gl.ELEMENT_ARRAY_BUFFER:索引数据
    • gl.COPY_READ_BUFFER/gl.COPY_WRITE_BUFFER:复制操作缓冲区
    • gl.TRANSFORM_FEEDBACK_BUFFER:变换反馈缓冲区
    • gl.UNIFORM_BUFFER:统一变量缓冲区
  2. size/data/srcData

    • 可以是指定缓冲区大小的数字
    • 或者是包含数据的 ArrayBufferTypedArrayDataView 对象
    • WebGL2 新增支持指定源数据的偏移和长度
  3. usage - 指定数据使用模式:

    • gl.STATIC_DRAW:数据内容很少更改
    • gl.DYNAMIC_DRAW:数据内容会频繁更改
    • gl.STREAM_DRAW:数据内容每次绘制都会更改
    • WebGL2 新增:gl.STATIC_READgl.DYNAMIC_READgl.STREAM_READ

WebGL2 新增特性

  1. 支持更多缓冲区类型(如统一变量缓冲区)
  2. 可以指定数据源的偏移和长度
  3. 增加了更多 usage 模式
  4. 支持使用 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 新增)
  • 数据格式必须与着色器中声明的属性类型匹配
相关推荐
qiao若huan喜3 天前
7、webgl 基本概念 + 前置数学知识点(向量 + 矩阵)
线性代数·矩阵·webgl
qiao若huan喜5 天前
6、webgl 基本概念 + 四边形纹理
前端·javascript·信息可视化·webgl
爱看书的小沐6 天前
【小沐杂货铺】基于Three.js绘制三维管道Pipe(WebGL、vue、react)
javascript·vue.js·webgl·three.js·管道·pipe·三维管道
梦凡尘7 天前
webgl 变换矩阵:旋转、平移、缩放
webgl
倚剑仙8 天前
Unity-WebGL开发——用IIS(Internet Information Services)部署webGL工程
unity·游戏引擎·webgl
xhload3d12 天前
热力图可视化为何被广泛应用?| 图扑数字孪生
3d·html5·webgl·数字孪生·可视化·热力图·三维建模·轻量化·电力能源·空间热力图
十年_H12 天前
Cesium 顶点着色器的数据来源
javascript·webgl·cesium
xhload3d18 天前
WebGL/Canvas 内存泄露分析
低代码·3d·html5·webgl·数字孪生·可视化·软件开发·工业互联网·内存泄漏·轻量化·技术应用·hightopo
爱看书的小沐20 天前
【小沐杂货铺】基于Three.js渲染三维风力发电机(WebGL、vue、react、WindTurbine)
javascript·vue.js·webgl·three.js·opengl·风力发电机·windturbine
郝学胜-神的一滴21 天前
Three.js光照技术详解:为3D场景注入灵魂
开发语言·前端·javascript·3d·web3·webgl