WebGl 使用缓冲区对象绘制多个点

缓冲区对象是WebGL系统中为一块内存区域,可以一次性地向缓冲区对象中填充大量的顶点数据,然后将这些数据保存在其中,供顶点着色器使用。

1.类型化数组类型

在 webgl 中,需要处理大量的相同类型数据,所以引入类型化数组,这样程序就可以预知到数组中的数据类型,提高性能。

  1. Int8Array:8位整型
  2. UInt8Array: 8位无符号整型
  3. Int16Array: 16位整型
  4. UInt16Array:16位无符号整型
  5. Int32Array:32位整型
  6. UInt32Array:32位无符号整型
  7. Float32Array:单精度32位浮点型
  8. Float64Array:双精度64位浮点型
const points = new Float32Array([
    -0.5, -0.5,
    0.5, -0.5,
    0.0, 0.5,
])

2.创建缓冲区对象 

const buffer = gl.createBuffer();

3.绑定缓冲区对象

gl.bindBuffer(target, buffer)

(1)target参数有两种:

  • gI.ARRAY_BUFFER: 表示缓冲区存储的是顶点的数据
  • 9I.ELEMENT_ARRAY_BUFFER:表示缓冲区存储的是顶点的索引值

(2)buffer:已经创建好的缓冲区对象

4.将数据写入缓冲区对象

gl.bufferData(target, data, type)

(1)target: 类型同 gl.bindBuffer 中的 target

(2)data:写入缓冲区的顶点数据,如程序中的 points

(3)type表示如何使用缓冲区对象中的数据,分为以下几类:

  • gI.STATIC DRAW:写入一次,多次绘制。
  • gI.STREAM_DRAW:写入一次,绘制若干次。
  • gI.DYNAMIC_DRAW:写入多次,绘制多次。

5.将缓冲区对象分配给一个attribute变量

gl.vertexAttribPointer(location, size, type, normalized, stride, offset)

(1)location:attribute 变量的存储位置

(2)size:指定每个顶点所使用数据的个数

(3)type:指定数据格式

  • gI.FLOAT:浮点型
  • 9I.UNSIGNED_BYTE:无符号字节
  • gI.SHORT:短整型
  • gI.UNSIGNED_SHORT:无符号短整型
  • gI.INT:整型
  • gI.UNSIGNED_INT:无符号整型

(4)normalized:表示是否将数据归一化到[0,1][-1,1]这个区间

(5)stride:两个相邻顶点之间的字节数

(6)offset:数据偏移量

6.开启attribute变量

gl.enableVertexAttribArray(location)

(1)location: attribute 变量的存储地址

(2)gl.disableVertexAttribArray(aPosition); 使用此方法禁用attribute变量

7.完整代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            margin: 50px auto;
            display: block;
            background: pink;
        }
    </style>
    <title>修改点的颜色</title>
</head>

<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持canvas
    </canvas>
    <script src="./js/index.js"></script>
    <script>
        const ctx = document.getElementById('canvas')
        const gl = ctx.getContext('webgl')
        // 顶点着色器源码
        const vertexShaderSource = `
            attribute vec4 aPosition;
            void main() {
                gl_Position = aPosition; 
                gl_PointSize = 10.0;
            }`

        // 片源着色器源码
        const fragmentShaderSource = `
            void main() {
                gl_FragColor = vec4(0.0,0.0,0.0,1.0); // r, g, b, a
            }`
        const program = initShader(gl, vertexShaderSource, fragmentShaderSource);
        const aPosition = gl.getAttribLocation(program, 'aPosition');

        // 1.创建顶点数据
        const points = new Float32Array([
            -0.5, -0.5,
            0.5, -0.5,
            0.0, 0.5,
        ])
        // 2.创建缓冲区对象
        const buffer = gl.createBuffer();
        // 3.绑定缓冲区对象
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
        // 4.将数据写入缓冲区对象,这里参数选择写入一次,多次绘制
        gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW)
        // 5.将缓冲区对象分配给一个attribute变量
        gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
        // 6.开启attribute变量
        gl.enableVertexAttribArray(aPosition)
        // 7.绘制三个点
        gl.drawArrays(gl.POINTS, 0, 3);


        // 着色器 
        function initShader(gl, vertexShaderSource, fragmentShaderSource) {
            const vertexShader = gl.createShader(gl.VERTEX_SHADER);
            const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(vertexShader, vertexShaderSource);
            gl.shaderSource(fragmentShader, fragmentShaderSource);
            gl.compileShader(vertexShader);
            gl.compileShader(fragmentShader);
            const program = gl.createProgram();
            gl.attachShader(program, vertexShader);
            gl.attachShader(program, fragmentShader);
            gl.linkProgram(program);
            gl.useProgram(program);
            return program;
        }
    </script>
</body>

</html>

8.效果如下

上一篇:JAVA地狱级笑话


下一篇:python教程:python中什么是类方法,类变量及其使用的案例