资讯专栏INFORMATION COLUMN

WebGL 绘制三角形

Lin_R / 3499人阅读

摘要:我们的目标是将位置信心从程序中传递到顶点着色器,而变量就传输的是那些和顶点相关的数据。缓冲区对象是中的一块存储区域,其中保存了大量的顶点数据,可以一次性的向顶点着色器传入多个顶点到变量。三角形一系列多带带的三角形。系列文章初探绘制三角形

该文章于一天前发表在 github,若有问题可提至 github。

在上一篇文章WebGL 初探中,我们熟悉了 WebGL 的简单背景以及如何绘制一个简单的点。但是只绘制点我们是无法进入三维世界的,本篇章将讲解如何使用 WebGL 绘制三角形,因为很多 3D 图形都是使用三角形为基础进行渲染的,所以有些对 GPU 性能指标的评价就是渲染三角形的能力。

attribute 变量

前一篇文章中,绘制一个点直接将一个硬编码的矢量赋给了位置属性。但是,显然这样写是不够灵活的。所以在这篇文章的前一部分会使用变量重些前一篇文章的例子。我们的目标是将位置信心从 JavaScript 程序中传递到顶点着色器,而 attribute 变量就传输的是那些和顶点相关的数据。下图展示了如何使用 attribute 变量传输数据:

var VSHADER_SOURCE =
  "attribute vec4 a_Position;
" +
  "void main() {
" +
  "  gl_Position = a_Position;
" +
  "  gl_PointSize = 10.0;
" +
  "}
";

如上所示,前一篇文章中,直接将使用矢量进行赋值 gl_Position = vec4(0.0, 0.0, 0.0, 1.0)。而这里使用 attribute vec4 a_Position 声明一个 attribute 变量。关键字 attribute 被称为存储限定符,表示声明一个 attribute 变量,而且 attribute 变量必须声明成全局变量,数据将从着色器外传入。gl_Position = a_Position 将 attribute 变量 a_Position 赋值给 gl_Position。

  // 获得 attribute 变量 a_Position 的存储位置
  var a_Position = gl.getAttribLocation(gl.program, "a_Position");
  if (a_Position < 0) {
    console.log("Failed to get the storage location of a_Position");
    return;
  }

  // 将顶点位置传递给 attribute 变量
  gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

上面,我们使用 vertexAttrib3f(location, v0, v1, v2) 方法将数据 (v0, v1, v2) 传递给 location 参数指向的 attribute 变量。而这里的 location 是要修改的 attribute 变量的存储位置。所以在这之前我们需要获取 attribute 变量的存储位置。这里,可以通过 getAttribLocation(program, name) 获取 attribute 变量的存储位置。进行完这些更改之后,运行会发现和上一篇文章相同的效果。

缓冲区对象

到现在,我们一次只能绘制一个点,无法一次性绘制多个点,甚至是线和面。想要一次绘制多个点,我们需要借助一个叫做缓冲区对象的东西。缓冲区对象是 WebGL 中的一块存储区域,其中保存了大量的顶点数据,可以一次性的向顶点着色器传入多个顶点到 attribute 变量。下图展示了如何使用缓冲区对象:

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

  // 创建缓冲区对象
  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("获得 attriute 变量 a_Position 失败");
    return -1;
  }
  // 将缓冲区对象赋值给 attriute 变量 a_Position
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

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

首先,是通过 createBuffer() 方法创建一个缓冲区对象,对应的方法还有 deleteBuffer() 用于删除一个缓冲区对象。接着,使用 bindBuffer(target, buffer) 将缓冲区对象绑定到 WebGL 已经存在的目标上,以通知 WebGL 正确的处理其内容。紧接着,使用 bufferData(target, data, useage) 方法将数据写入缓冲区,这里实际是将数据写入到绑定的目标对象上,所以在第二步中进行了缓冲区对象的绑定。而第二个参数是一个定义好的类型化数组。这里的第三个参数,STATIC_DRAW 代表只会想缓冲区写入一次,绘制多次,其它用法参数可查相关 API。然后,使用 vertexAttribPointer(location, size, type, normalized, stride, offset) 将缓冲区对象赋值给 attribute 变量。这里的第二个参数制定缓冲区对象的每个顶点的分量(1到4之间),如果 size 比 attribute 变量需要的分量小,则按照一定规则补全。第三个参数指定了数据格式。第四个参数表示是否将非浮点型数据归一到 [0, 1] 或[-1,1] 之间。最后两个参数一般默认为0,此处不做具体介绍。最后通过 enableVertexAttribArray(a_Position) 方法开启缓冲区对象和 attribute 变量的连接。

绘制三角形

最后,我么可通过 drawArrays(gl.TRIANGLES, 0, n) 绘制三角形。但是,前一篇文章中提到 drawArrays 函数功能非常强大。现在,我们就看一下该函数有哪些强大的特性。该函数中第一个参数是指定绘制方式,第二个参数指定从哪个顶点开始绘制,第三个参数指定绘制需要多少个顶点。下表展示了第一个参数对应的绘制方式:

参数 基本图形 呈现效果
gl.POINTS 一系列的点绘制在v0,v1,v2等处。
gl.LINES 线段 一系列多带带线段。
gl.LINE_STRIP 连线 一个相连的线段。
gl.LINE_LOOP 回路 一个相连接的回路。
gl.TRIANGLES 三角形 一系列多带带的三角形。
gl.TRIANGLE_STRIP 三角带 一个相邻三角形组成的图形。

下图是 new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5]) 矢量的一个测试:

结语

这篇文章主要讲了如何利用缓冲区对象在空间中绘制点、线、面。下一篇文章将讲解矩阵变换,有了这两个知识的积累,理论上可以画出我们想要的 3D 图形。WebGL 的 API 看似复杂,但基本都很类似。当我们对这一套熟悉之后,我们会愈发轻车熟路。

系列文章

WebGL 初探

绘制三角形

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80679.html

相关文章

  • WebGL 单通道wireframe渲染

    摘要:那是因为,线条的光栅化过程和多边形的光栅化过程并不是完全一致的。这将会导致一些本该被隐藏的线段,未被遮挡。原理我们知道,一般对象都是由三角形组成的。其中涉及到和的相关介绍,笔者将会在后续的文章中介绍。 如果要把一个对象的线框绘制出来,一般的方法是先绘制实体对象,然后通过gl.LINES的模式再绘制一遍模型,此时模型的线框就会被绘制出来。 gl.LINES的问题 此方法需要绘制两遍对象...

    KoreyLee 评论0 收藏0
  • SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

    摘要:在文末,我会附上一个可加载的模型方便学习中文艺术字渲染用原生可以很容易地绘制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 Web...

    objc94 评论0 收藏0

发表评论

0条评论

Lin_R

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<