Skip to content

上节我们通过三角形的绘制方式,了解到 WebGL 开发的基本要素,以及如何通过缓冲区向着色器传递数据。本节我们学习最后一种基本图元线段

本节内容虽然简单,但是我仍然想向那些钟爱 WebGL 的新手同学们详细地讲解一下,毕竟这是 WebGL 知识体系中的一部分,有经验的同学可以略过哈~

目标

本节通过鼠标点击动态绘制线段的示例,学习线段图元的分类以及绘制特点,效果如下:

线段图元的分类

线段图元分为三种:

  • LINES:基本线段。
  • LINE_STRIP:带状线段。
  • LINE_LOOP:环状线段。

接下来我们还是以实战为主,练习线段图元的绘制,并介绍他们之间的区别。

LINES 图元

LINES 图元称为基本线段图元,绘制每一条线段都需要明确指定构成线段的两个端点。

我们还是通过每次点击产生一个点,并将点击位置坐标放进 positions 数组中。

注意,我们的坐标还是相对于屏幕坐标系,顶点着色器中会将屏幕坐标系转换到裁剪坐标系,也就是坐标区间在[-1, 1]之间。

javascript
var positions = [];
canvas.addEventListener('mouseup', e => {
    var x = e.pageX;
    var y = e.pageY;
    positions.push(x);
    positions.push(y);
    if (positions.length > 0) {
        gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array(positions),
        gl.DYNAMIC_DRAW
    );
        render(gl);
    }
});

之后进行绘制,注意执行 drawArrays 时,图元参数应该设置为 gl.LINES。

javascript
gl.drawArrays(gl.LINES, 0, positions.length / 2);

可以看到,每次点击两次之后才能绘制一条新的线段,也就是说,采用 gl.LINES 进行绘制的话,必须制定两个端点坐标。

基本线段图元的绘制比较简单,我们看一下带状线段的绘制特点。

LINE_STRIP

LINE_STRIP 图元的绘制特点和 LINES 的有所区别,在绘制线段时,它会采用前一个顶点作为当前线段的起始端点。我们还是通过一个例子理解一下。

依然采用上面的代码,只不过这次在绘制时,将图元设置为 LINE_STRIP:

javascript
gl.drawArrays(gl.LINE_STRIP, 0, positions.length);

可以看到,除了第一条线段需要指定两个端点,之后每次点击一个新的点,都会自动绘制一条新线段,新线段的起点是上一个线段的终点。

LINE_STRIP 也比较简单,接下来看下环状线段LINE_LOOP的特点。

LINE_LOOP

顾名思义,环状线段除了包含 LINE_STRIP 的绘制特性,还有一个特点就是将线段的终点和第一个线段的起点进行连接,形成一个线段闭环。

废话不多说,看下效果大家就明白了。

注意,不要忘记将绘制图元更改为 LINE_LOOP

javascript
gl.drawArrays(gl.LINE_LOOP, 0, positions.length);

回顾

线段图元的绘制方式到此就结束了,比较简单。我们可以用线段做路线标注,也可以用它绘制一些线状图形,再加上一些动画做出有创意的效果。

事实上,webgl 的知识是有限的,但是我们的创意是无限的,有的时候并不需要技术多牛逼,只要创意够好,简单的技术也能实现让人惊艳的效果。

题外话:我一直觉得我的想象力是很差的,有时候还不如自己三岁的女儿。在做这个 demo 的时候,我女儿的一次胡乱点击,让我大吃一惊,她的绘制路径像极了一个五角星,我在此大致还原了一下她的点击路径:

一个胖胖、扁扁的的五角星,PS:偷笑。

下一节进入本节的一个重点,我会通过绘制渐变三角形来带大家深入学习顶点缓冲区的使用,并解答第三章节的三个遗留问题。