WebGL 绘制三角形

该文章于一天前宣布在 github,如有题目可提至 github

在上一篇文章WebGL 初探中,我们熟习了 WebGL 的简朴背景以及怎样绘制一个简朴的点。然则只绘制点我们是没法进入三维天下的,本篇章将解说怎样运用 WebGL 绘制三角形,由于许多 3D 图形都是运用三角形为基础举行衬着的,所以有些对 GPU 性能指标的评价就是衬着三角形的才能。

attribute 变量

前一篇文章中,绘制一个点直接将一个硬编码的矢量赋给了位置属性。然则,明显如许写是不够天真的。所以在这篇文章的前一部分会运用变量重些前一篇文章的例子。我们的目的是将位置自信心从 JavaScript 顺序中通报到极点着色器,而 attribute 变量就传输的是那些和极点相干的数据。下图展现了怎样运用 attribute 变量传输数据:

《WebGL 绘制三角形》

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

如上所示,前一篇文章中,直接将运用矢量举行赋值 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 变量。下图展现了怎样运用缓冲区对象:

《WebGL 绘制三角形》

  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]) 矢量的一个测试:

《WebGL 绘制三角形》

结语

这篇文章重要讲了怎样应用缓冲区对象在空间中绘制点、线、面。下一篇文章将解说矩阵变更,有了这两个学问的积聚,理论上能够画出我们想要的 3D 图形。WebGL 的 API 看似庞杂,但基础都很相似。当我们对这一套熟习以后,我们会愈发驾轻就熟。

系列文章

    原文作者:sundway
    原文地址: https://segmentfault.com/a/1190000007167115
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞