WebGL - 通过缓冲区对象绘制多个点的过程

1、绘制多个点的过程

绘制一个点的时候,webgl程序的执行过程是这样的:

  • 获取 webgl 绘图上下文
  • 初始化着色器
  • 设置 canvas 背景色
  • 清空 canvas
  • 开始绘制

上面是绘制一个点的过程,但是如果想要绘制多个点话,就需要多次重复上面的步骤吗?

webgl提供了一种机制可以向缓存中一次存储多个顶点的信息,然后只需要循环的调用 着色器程序即可,而不需要循环重复上面的步骤。

因此上面的步骤中多个一个 步骤 :设置点的坐标信息 然后再清空 canvas 再绘制

2、创建三个顶点

具体步骤如下

1、首先顶点着色器和片元着色器不用换

attibute vec4 a_Position;
void main(){
    gl_Position = a_Position;
    gl_PointSize = 10.0;
}
void main(){
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

2、设置顶点位置

  • 1、创建缓冲区对象 – gl.createBuffer()
  • 2、绑定缓冲区对象 – gl.bindBuffer()
  • 3、将数据写入缓冲区对象 – gl.bufferData()
  • 4、将缓冲区对象分配给一个 attribute变量 gl.vertexAttribPointer()
  • 5、开启attribute变量 – gl.enableVertexAttribArray()

缓冲区对象: 缓冲区对象是 webgl 系统中的一块存储区,我们可以在缓冲区对象中保存想要绘制的所有顶点的数据,并且可以使用也可以不使用;

使用缓冲区对象向顶点着色器传入数据,需要遵守以上五个步骤;

具体代码如下

var vertices = new Float32Array([
    0.0, 0.5, 0.5, -0.5, -0.5, -0.5
]);

var n = vertices.length / 2;

// 1. 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
    console.log('创建缓冲区对象失败!');
    return -1;
}

// 2. 绑定缓冲区对象到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

// 3. 将数据写入到缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
    console.log('获取attribute变量失败!');
    return -1;
}

// 4. 将缓冲区对象分配给attribute变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

// 5. 开启attribute变量
gl.enableVertexAttribArray(a_Position);

具体细节如下

1、 创建缓冲区对象
var vertexBuffer = gl.createBuffer();

创建缓冲区对象不用传递参数,创建一个对象就存留在 webgl的缓冲区中,不删除则一致存在

删除缓冲区的方法

gl.deleteBuffer(buffer);

删除的时候传入的参数是,缓冲区的引用

2、绑定缓冲区对象到目标
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);

将缓冲区对象绑定到 webgl中已经存在的目标上,目标表示缓冲区对象的用途,这里传递的是gl.ARRAY_BUFFER表示缓冲区对象中包含顶点的数据,另外还可以传递gl.ELEMENT_ARRAY_BUFFER这个表示缓冲区对象包含了顶点的索引值;

第二个参数是刚刚创建的缓冲区对象

3、将数据写入缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DEAW)

这个方法的作用是将顶点数组vertices的数据,写入到已经绑定了缓冲区的对象中,第三个参数是写入和绘制次数限制;

4、分配缓冲区对象
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

之前绘制一个顶点的时候,是通过gl.vertexAttrib[123]f()attribute分配变量值,但是这个方法一次只能分配一个值,而此时我们需要将整个缓冲区里面的值全部分配给 attribute变量,此时就需要使用gl.vertexAttribPointer()它可以将整缓冲区对象的引用分配给attribute变量;

gl.vertexAttribPointer(location, size, type, normalized, stride,offset)具体参数

  • location:待分配的 attribute变量
  • size:指定缓冲区每个顶点的分量个数(1 - 4)
  • type:指定数据格式
  • normalize:表示浮点型的数据是否归一化到[0, 1]或者[-1,1]区间
  • stride:指定相邻两个顶点间的字节数,默认为0
  • offset:指定缓冲区对象的偏移量,以字节为单位,若是从起始位置开始,offset设置0
5、开启 attribute 变量

为了使顶点着色器能够访问缓冲区的数据,还需要开始attribute变量

gl.enableVertexAttribArray(a_Position);

此时缓冲区对象就和attribute之间建立了连接,也可也通过以下方法来关闭连接

gl.disableVertexArray(location)

通过以上五个步骤就可以绘制顶点了,具体的绘制方式和绘制次数还需要在gl.drawArrays()中,来设置;

gl.drawArrays(gl.POINTS, 0, 3);

上面代码表示,绘制点从第一个点开始,绘制三个点,此时顶点着色器执行了3次,也就是最后一个参数的设置;
在这里插入图片描述
示例地址
绘制多个点
示例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="../css/common.css">
</head>
<body>
<canvas id="webgl" width="512" height="512"></canvas>
</body>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>

<script>

    // 顶点着色器
    var vertex_shader_source = '' +
        'attribute vec4 a_Position;' +
        'void main() {' +
        '   gl_Position = a_Position;' +
        '   gl_PointSize = 10.0;' +
        '}';

    // 片元着色器
    var fragment_shader_source = '' +
        'void main(){' +
        '   gl_FragColor = vec4(0.5, 0.0, 0.5, 1.0);' +
        '}';

    (function () {

        // 获取canvas对象
        var canvas = document.getElementById('webgl');

        // 获取webgl 上下文对象
        var gl = getWebGLContext(canvas);

        // 初始化着色器
        if (!initShaders(gl, vertex_shader_source, fragment_shader_source)) {
            console.log('初始化着色器失败!');
            return false;
        }

        // 设置顶点位置
        var n = initVertexBuffer(gl);
        if (n < 0) {
            console.log('顶点写入缓存失败!');
            return false;
        }

        // 设置清空颜色
        gl.clearColor(0.0, 0.5, 0.5, 1.0);

        // 清空canvas
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.drawArrays(gl.POINTS, 0, n);

        // 将顶点信息写入缓存区
        function initVertexBuffer(gl) {

            var vertices = new Float32Array([
               0.0, 0.5, 0.5, -0.5, -0.5, -0.5
            ]);

            var n = vertices.length / 2;

            // 创建缓冲区对象
            var vertexBuffer = gl.createBuffer();
            if (!vertexBuffer) {
                console.log('创建缓冲区对象失败!');
                return -1;
            }

            // 绑定缓冲区对象到目标
            gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

            // 将数据写入到缓冲区对象
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

            var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
            if (a_Position < 0) {
                console.log('获取attribute变量失败!');
                return -1;
            }

            // 将缓冲区对象分配给attribute变量
            gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

            // 开启attribute变量
            gl.enableVertexAttribArray(a_Position);

            return n;

        }

    }());

</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值