WebGL本事储备指南,手艺储备指南
分类:计算机知识

WebGL本事储备指南

2015/12/22 · HTML5 · 1 评论 · WebGL

初稿出处: 天猫前端团队(FED)- 叶斋   

威尼斯手机娱乐官网 1

WebGL 是 HTML 5 草案的一有的,能够使得 Canvas 渲染三个维度场景。WebGL 即便还未有广泛应用,但极具潜质和想象空间。本文是自家读书 WebGL 时梳理知识系统的产物,花点时间整理出来与大家享用。

WebGL 是 HTML 5 草案的一有的,能够使得 Canvas 渲染空间维度场景。WebGL 即便还未有遍布应用,但极具潜在的能量和设想空间。本文是自身上学 WebGL 时梳理知识系统的产物,花点时间整理出来与大家享用。

示例

WebGL 很酷,有以下 demos 为证:

威尼斯手机娱乐官网 ,搜求奥兹国
赛车游戏
泛舟的男孩(Goo Engine Demo)

示例

WebGL 很酷,有以下 demos 为证:

搜索奥兹国
超跑游戏
泛舟的男孩(Goo Engine Demo)

本文的靶子

正文的料想读者是:不熟知图形学,熟知前端,希望通晓或系统学习 WebGL 的校友。

本文不是 WebGL 的概述性文章,亦不是完整详细的 WebGL 教程。本文只盼望成为一篇供 WebGL 初学者使用的总纲。

正文的对象

正文的意料读者是:素不相识图形学,熟知前端,希望驾驭或类别学习 WebGL 的同班。

正文不是 WebGL 的概述性作品,亦不是一体化详细的 WebGL 教程。本文只愿意形成一篇供 WebGL 初学者使用的纲领。

Canvas

明白 Canvas 的校友都领悟,Canvas 绘图先要获取绘图上下文:

JavaScript

var context = canvas.getContext('2d');

1
var context = canvas.getContext('2d');

context上调用各类函数绘制图形,比方:

JavaScript

// 绘制左上角为(0,0),右下角为(50, 50)的矩形 context.fillRect(0, 0, 50, 50);

1
2
// 绘制左上角为(0,0),右下角为(50, 50)的矩形
context.fillRect(0, 0, 50, 50);

WebGL 同样必要得到绘图上下文:

JavaScript

var gl = canvas.getContext('webgl'); // 或 experimental-webgl

1
var gl = canvas.getContext('webgl'); // 或 experimental-webgl

唯独接下去,假设想画二个矩形的话,就没这么轻易了。实际上,Canvas 是浏览器封装好的贰个绘制蒙受,在事实上海展览中心开绘图操作时,浏览器还是要求调用 OpenGL API。而 WebGL API 大约正是 OpenGL API 未经封装,直接套了一层壳。

Canvas 的越来越多文化,能够参见:

  • JS 权威指南的 21.4 节或 JS 高档程序设计中的 15 章
  • W3CSchool
  • 阮一峰的 Canvas 教程

Canvas

熟识 Canvas 的同窗都理解,Canvas 绘图先要获取绘图上下文:

var context = canvas.getContext('2d');

context上调用各类函数绘制图形,比方:

// 绘制左上角为(0,0),右下角为(50, 50)的矩形
context.fillRect(0, 0, 50, 50);

WebGL 一样要求获得绘图上下文:

var gl = canvas.getContext('webgl'); // 或 experimental-webgl

唯独接下去,假若想画三个矩形的话,就没这么轻巧了。实际上,Canvas 是浏览器封装好的叁个制图遭逢,在实质上进行绘图操作时,浏览器依旧供给调用 OpenGL API。而 WebGL API 大概便是 OpenGL API 未经封装,直接套了一层壳。

Canvas 的越多文化,能够参见:

  • JS 权威指南的 21.4 节或 JS 高档程序设计中的 15 章
  • W3CSchool
  • 阮一峰的 Canvas 教程

矩阵转变

三维模型,从文件中读出来,到绘制在 Canvas 中,经历了频仍坐标调换。

借使有三个最简便易行的模子:三角形,三个终端分别为(-1,-1,0),(1,-1,0),(0,1,0)。那多个数据是从文件中读出来的,是三角形最开端的坐标(局地坐标)。如下图所示,左臂坐标系。

威尼斯手机娱乐官网 2

模型日常不会放在场景的原点,假诺三角形的原点位于(0,0,-1)处,未有转动或缩放,八个极端分别为(-1,-1,-1),(1,-1,-1),(0,1,-1),即世界坐标。

威尼斯手机娱乐官网 3

绘图空间维度场景必需钦点三个阅览者,要是观看者位于(0,0,1)处並且看向三角形,那么八个终端绝对于观看者的坐标为(-1,-1,-2),(1,-1,-2),(0,1,-2),即视图坐标。

威尼斯手机娱乐官网 4

阅览者的眼眸是四个点(那是看破投影的前提),水平视角和垂直视角都是90度,视线范围(目力所及)为[0,2]在Z轴上,观看者能够看到的区域是八个四棱台体。

威尼斯手机娱乐官网 5

将四棱台体映射为正式立方(CCV,宗旨为原点,边长为2,边与坐标轴平行)。顶点在 CCV 中的坐标,离它最后在 Canvas 中的坐标已经很类似了,如若把 CCV 的前表面看成 Canvas,那么最后三角形就画在图中油红三角形的地方。

威尼斯手机娱乐官网 6

上述转换是用矩阵来张开的。

有个别坐标 –(模型转换)-> 世界坐标 –(视图转换)-> 视图坐标 –(投影调换)–> CCV 坐标。

以(0,1,0)为例,它的齐次向量为(0,0,1,1),上述转变的象征经过可以是:

威尼斯手机娱乐官网 7

地方多个矩阵依次是看破投影矩阵,视图矩阵,模型矩阵。八个矩阵的值分别取决于:观望者的眼光和视线距离,阅览者在世界中的状态(地点和可行性),模型在世界中的状态(地方和自由化)。计算的结果是(0,1,1,2),化成齐次坐标是(0,0.5,0.5,1),正是其一点在CCV中的坐标,那么(0,0.5)正是在Canvas中的坐标(认为Canvas 中央为原点,长度宽度都为2)。

上边出现的(0,0,1,1)是(0,0,1)的齐次向量。齐次向量(x,y,z,w)能够表示三个维度向量(x,y,z)加入矩阵运算,通俗地说,w 分量为 1 时表示地方,w 分量为 0 时表示位移。

WebGL 没有提供任何有关上述转换的建制,开垦者须要亲自总计顶点的 CCV 坐标。

有关坐标转变的更多内容,能够参照他事他说加以考察:

  • Computer图形学中的5-7章
  • 更改矩阵@维基百科
  • 透视投影详解

相比复杂的是模型转变中的绕放肆轴旋转(平日用四元数生成矩阵)和投影转换(上边的事例都没收涉及到)。

关于绕狂妄轴旋转和四元数,能够参照:

  • 四元数@维基百科
  • 一个鬼子对四元数公式的表明

有关齐次向量的越多内容,可以参照他事他说加以考察。

  • Computer图形学的5.2节
  • 齐次坐标@维基百科

矩阵转变

三维模型,从文件中读出来,到绘制在 Canvas 中,经历了往往坐标转变。

万一有五个最简易的模子:三角形,四个极点分别为(-1,-1,0),(1,-1,0),(0,1,0)。那四个数据是从文件中读出来的,是三角形最起头的坐标(局地坐标)。如下图所示,右臂坐标系。

威尼斯手机娱乐官网 8

模型经常不会放在场景的原点,假使三角形的原点位于(0,0,-1)处,未有转动或缩放,七个顶峰分别为(-1,-1,-1),(1,-1,-1),(0,1,-1),即世界坐标。

威尼斯手机娱乐官网 9

绘图三个维度场景必须钦赐一个观望者,假诺观看者位于(0,0,1)处並且看向三角形,那么八个极点相对于观望者的坐标为(-1,-1,-2),(1,-1,-2),(0,1,-2),即视图坐标。

威尼斯手机娱乐官网 10

观看者的眼睛是贰个点(那是看破投影的前提),水平视角和垂直视角都以90度,视界范围(目力所及)为[0,2]在Z轴上,观望者能够见到的区域是三个四棱台体。

威尼斯手机娱乐官网 11

将四棱台体映射为正式立方(CCV,中央为原点,边长为2,边与坐标轴平行)。顶点在 CCV 中的坐标,离它提起底在 Canvas 中的坐标已经很临近了,假诺把 CCV 的前表面看成 Canvas,那么最后三角形就画在图中青古铜色三角形的岗位。

威尼斯手机娱乐官网 12

上述调换是用矩阵来扩充的。

有个别坐标 –(模型转换)-> 世界坐标 –(视图转变)-> 视图坐标 –(投影变换)–> CCV 坐标。

以(0,1,0)为例,它的齐次向量为(0,0,1,1),上述调换的意味经过能够是:

威尼斯手机娱乐官网 13

上边四个矩阵依次是看破投影矩阵,视图矩阵,模型矩阵。五个矩阵的值分别取决于:旁观者的眼光和视线距离,观望者在世界中的状态(地点和可行性),模型在世界中的状态(地方和取向)。总计的结果是(0,1,1,2),化成齐次坐标是(0,0.5,0.5,1),就是其一点在CCV中的坐标,那么(0,0.5)正是在Canvas中的坐标(以为Canvas 主旨为原点,长宽都为2)。

地点现身的(0,0,1,1)是(0,0,1)的齐次向量。齐次向量(x,y,z,w)能够代表三个维度向量(x,y,z)出席矩阵运算,通俗地说,w 分量为 1 时表示地点,w 分量为 0 时表示位移。

WebGL 未有提供别的关于上述转变的机制,开荒者需求亲自计算顶点的 CCV 坐标。

关于坐标转换的越来越多内容,可以参照:

  • 计算机图形学中的5-7章
  • 转变矩阵@维基百科
  • 透视投影详解

相比复杂的是模型调换中的绕大肆轴旋转(平日用四元数生成矩阵)和投影调换(上边的例证都没收涉及到)。

至于绕大肆轴旋转和四元数,能够参见:

  • 四元数@维基百科
  • 一个鬼子对四元数公式的证实

关于齐次向量的越多内容,能够参照。

  • 微型Computer图形学的5.2节
  • 齐次坐标@维基百科

着色器和光栅化

在 WebGL 中,开荒者是通过着色器来成功上述转换的。着色器是运作在显卡中的程序,以 GLSL 语言编写,开垦者须要将着色器的源码以字符串的方式传给 WebGL 上下文的有关函数。

着色器有二种,顶点着色器和片元(像素)着色器,它们成对出现。顶点着色器任务是收到顶点的一对坐标,输出 CCV 坐标。CCV 坐标经过光栅化,转化为逐像素的数量,传给片元着色器。片元着色器的职责是规定各种片元的颜色。

终端着色器接收的是 attribute 变量,是逐顶点的数据。顶点着色器输出 varying 变量,也是逐顶点的。逐顶点的 varying 变量数据经过光栅化,成为逐片元的 varying 变量数据,输入片元着色器,片元着色器输出的结果就能够显得在 Canvas 上。

威尼斯手机娱乐官网 14

着色器功用相当多,上述只是基本功效。当先四分之二光彩夺目的机能都以凭仗着色器的。假诺您对着色器完全未有定义,能够试着明亮下一节 hello world 程序中的着色器再回首一下本节。

关于越来越多着色器的学问,能够参见:

  • GLSL@维基百科
  • WebGL@MSDN

着色器和光栅化

在 WebGL 中,开荒者是通过着色器来成功上述调换的。着色器是运作在显卡中的程序,以 GLSL 语言编写,开采者要求将着色器的源码以字符串的格局传给 WebGL 上下文的相干函数。

着色器有三种,顶点着色器和片元(像素)着色器,它们成对出现。顶点着色器义务是接受顶点的一对坐标,输出 CCV 坐标。CCV 坐标经过光栅化,转化为逐像素的多少,传给片元着色器。片元着色器的天职是规定每种片元的水彩。

终极着色器接收的是 attribute 变量,是逐顶点的多少。顶点着色器输出 varying 变量,也是逐顶点的。逐顶点的 varying 变量数据经过光栅化,成为逐片元的 varying 变量数据,输入片元着色器,片元着色器输出的结果就能够显得在 Canvas 上。

威尼斯手机娱乐官网 15

着色器功用非常多,上述只是基本作用。大多数光彩夺目的效用都以借助着色器的。假如您对着色器完全未有定义,能够试着明亮下一节 hello world 程序中的着色器再回首一下本节。

关于越多着色器的学问,可以参照:

  • GLSL@维基百科
  • WebGL@MSDN

程序

这一节解释绘制上述场景(三角形)的 WebGL 程序。点那几个链接,查看源代码,试图懂得一下。这段代码出自WebGL Programming Guide,作者作了一部分修改以适应本文内容。假使一切正常,你看看的应有是下边那样:

威尼斯手机娱乐官网 16

解释几点(就算此前不驾驭 WebGL ,多半会对上面包车型地铁代码思疑,无碍):

  1. 字符串 VSHADER_SOURCE 和 FSHADER_SOURCE 是终端着色器和片元着色器的源码。能够将着色器明白为有固定输入和出口格式的程序。开采者须要事先编写好着色器,再根据一定格式着色器发送绘图命令。
  2. Part2 将着色器源码编写翻译为 program 对象:先分别编写翻译顶点着色器和片元着色器,然后连接两者。假使编写翻译源码错误,不会报 JS 错误,但足以由此任何 API(如gl.getShaderInfo等)获取编写翻译状态新闻(成功与否,尽管出错的错误新闻)。
JavaScript

// 顶点着色器 var vshader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vshader, VSHADER_SOURCE);
gl.compileShader(vshader); // 同样新建 fshader var program =
gl.createProgram(); gl.attachShader(program, vshader);
gl.attachShader(program, fshader); gl.linkProgram(program);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f14b3a671c960813930-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a671c960813930-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a671c960813930-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a671c960813930-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a671c960813930-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a671c960813930-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a671c960813930-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a671c960813930-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a671c960813930-9">
9
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f14b3a671c960813930-1" class="crayon-line">
// 顶点着色器
</div>
<div id="crayon-5b8f14b3a671c960813930-2" class="crayon-line crayon-striped-line">
var vshader = gl.createShader(gl.VERTEX_SHADER);
</div>
<div id="crayon-5b8f14b3a671c960813930-3" class="crayon-line">
gl.shaderSource(vshader, VSHADER_SOURCE);
</div>
<div id="crayon-5b8f14b3a671c960813930-4" class="crayon-line crayon-striped-line">
gl.compileShader(vshader);
</div>
<div id="crayon-5b8f14b3a671c960813930-5" class="crayon-line">
// 同样新建 fshader
</div>
<div id="crayon-5b8f14b3a671c960813930-6" class="crayon-line crayon-striped-line">
var program = gl.createProgram();
</div>
<div id="crayon-5b8f14b3a671c960813930-7" class="crayon-line">
gl.attachShader(program, vshader);
</div>
<div id="crayon-5b8f14b3a671c960813930-8" class="crayon-line crayon-striped-line">
gl.attachShader(program, fshader);
</div>
<div id="crayon-5b8f14b3a671c960813930-9" class="crayon-line">
gl.linkProgram(program);
</div>
</div></td>
</tr>
</tbody>
</table>
  1. program 对象急需钦定使用它,才足以向着色器传数据并绘制。复杂的次第常常有四个program 对 象,(绘制每一帧时)通过切换 program 对象绘制场景中的分歧功用。
JavaScript

gl.useProgram(program);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f14b3a6720232020477-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f14b3a6720232020477-1" class="crayon-line">
gl.useProgram(program);
</div>
</div></td>
</tr>
</tbody>
</table>
  1. Part3 向正在采纳的着色器传入数据,包含逐顶点的 attribute 变量和大局的 uniform 变量。向着色器传入数据必需采纳ArrayBuffer,并不是正规的 JS 数组。
JavaScript

var varray = new Float32Array([-1, -1, 0, 1, -1, 0, 0, 1, 0])

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f14b3a6723482450329-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f14b3a6723482450329-1" class="crayon-line">
var varray = new Float32Array([-1, -1, 0, 1, -1, 0, 0, 1, 0])
</div>
</div></td>
</tr>
</tbody>
</table>
  1. WebGL API 对 ArrayBuffer 的操作(填充缓冲区,传入着色器,绘制等)都以经过 gl.A本田CR-VRAY_BUFFE奥迪Q5实行的。在 WebGL 系统中又相当多近乎的情景。
JavaScript

// 只有将 vbuffer 绑定到 gl.ARRAY_BUFFER,才可以填充数据
gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer); // 这里的意思是,向“绑定到
gl.ARRAY_BUFFER”的缓冲区中填充数据 gl.bufferData(gl.ARRAY_BUFFER,
varray, gl.STATIC_DRAW); // 获取 a_Position
变量在着色器程序中的位置,参考顶点着色器源码 var aloc =
gl.getAttribLocation(program, 'a_Position'); // 将 gl.ARRAY_BUFFER
中的数据传入 aloc 表示的变量,即 a_Position
gl.vertexAttribPointer(aloc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aloc);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f14b3a6727492492738-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a6727492492738-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a6727492492738-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a6727492492738-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a6727492492738-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a6727492492738-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a6727492492738-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f14b3a6727492492738-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f14b3a6727492492738-9">
9
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f14b3a6727492492738-1" class="crayon-line">
// 只有将 vbuffer 绑定到 gl.ARRAY_BUFFER,才可以填充数据
</div>
<div id="crayon-5b8f14b3a6727492492738-2" class="crayon-line crayon-striped-line">
gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
</div>
<div id="crayon-5b8f14b3a6727492492738-3" class="crayon-line">
// 这里的意思是,向“绑定到 gl.ARRAY_BUFFER”的缓冲区中填充数据
</div>
<div id="crayon-5b8f14b3a6727492492738-4" class="crayon-line crayon-striped-line">
gl.bufferData(gl.ARRAY_BUFFER, varray, gl.STATIC_DRAW);
</div>
<div id="crayon-5b8f14b3a6727492492738-5" class="crayon-line">
// 获取 a_Position 变量在着色器程序中的位置,参考顶点着色器源码
</div>
<div id="crayon-5b8f14b3a6727492492738-6" class="crayon-line crayon-striped-line">
var aloc = gl.getAttribLocation(program, 'a_Position');
</div>
<div id="crayon-5b8f14b3a6727492492738-7" class="crayon-line">
// 将 gl.ARRAY_BUFFER 中的数据传入 aloc 表示的变量,即 a_Position
</div>
<div id="crayon-5b8f14b3a6727492492738-8" class="crayon-line crayon-striped-line">
gl.vertexAttribPointer(aloc, 3, gl.FLOAT, false, 0, 0);
</div>
<div id="crayon-5b8f14b3a6727492492738-9" class="crayon-line">
gl.enableVertexAttribArray(aloc);
</div>
</div></td>
</tr>
</tbody>
</table>
  1. 向着色器传入矩阵时,是按列存款和储蓄的。能够比较一下 mmatrix 和矩阵转变一节中的模型矩阵(第 3 个)。
  2. 极端着色器总计出的 gl_Position 正是 CCV 中的坐标,比如最下面的极端(洋红)的 gl_Position 化成齐次坐标正是(0,0.5,0.5,1)。
  3. 向终极着色器传入的只是八个终端的颜色值,而三角形表面包车型地铁水彩渐变是由这些颜色值内插出的。光栅化不唯有会对 gl_Position 实行,还有恐怕会对 varying 变量插值。
  4. gl.drawArrays()方法使得缓冲区进行绘图,gl.T奥迪PB18IANGLES 钦定绘制三角形,也得以转移参数绘制点、折线等等。

有关 ArrayBuffer 的详细新闻,能够参照:

  • ArrayBuffer@MDN
  • 阮一峰的 ArrayBuffer 介绍
  • 张鑫旭的 ArrayBuffer 介绍

有关 gl.T陆风X8IANGLES 等别的绘制格局,能够参谋上面那张图或那篇博文。

威尼斯手机娱乐官网 17

程序

这一节解释绘制上述情景(三角形)的 WebGL 程序。点其一链接,查看源代码,试图理解一下。这段代码出自WebGL Programming Guide,小编作了有个别更改以适应本文内容。假使一切不荒谬,你见到的应当是底下那样:

威尼斯手机娱乐官网 18

分解几点(如若从前不打听 WebGL ,多半会对上面包车型地铁代码嫌疑,无碍):

  1. 字符串 VSHADER_SOURCE 和 FSHADER_SOURCE 是极端着色器和片元着色器的源码。能够将着色器掌握为有稳固输入和出口格式的顺序。开采者供给事先编写好着色器,再依据一定格式着色器发送绘图命令。

  2. Part2 将着色器源码编写翻译为 program 对象:先分别编译顶点着色器和片元着色器,然后连接两个。假若编写翻译源码错误,不会报 JS 错误,但能够通过其余API(如gl.getShaderInfo等)获取编写翻译状态音信(成功与否,假设出错的错误新闻)。

    // 顶点着色器
    var vshader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vshader, VSHADER_SOURCE);
    gl.compileShader(vshader);
    // 同样新建 fshader
    var program = gl.createProgram();
    gl.attachShader(program, vshader);
    gl.attachShader(program, fshader);
    gl.linkProgram(program);
    
  3. program 对象须要内定使用它,才方可向着色器传数据并绘制。复杂的程序日常有多少个program 对 象,(绘制每一帧时)通过切换 program 对象绘制场景中的分歧成效。

    gl.useProgram(program);
    
  4. Part3 向正在选拔的着色器传入数据,包涵逐顶点的 attribute 变量和大局的 uniform 变量。向着色器传入数据必需运用 ArrayBuffer,实际不是例行的 JS 数组。

    var varray = new Float32Array([-1, -1, 0, 1, -1, 0, 0, 1, 0])
    
  5. WebGL API 对 ArrayBuffer 的操作(填充缓冲区,传入着色器,绘制等)都以经过 gl.AXC90RAY_BUFFE中华V举办的。在 WebGL 系统中又相当多近似的情况。

    // 只有将 vbuffer 绑定到 gl.ARRAY_BUFFER,才可以填充数据
    gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
    // 这里的意思是,向“绑定到 gl.ARRAY_BUFFER”的缓冲区中填充数据
    gl.bufferData(gl.ARRAY_BUFFER, varray, gl.STATIC_DRAW);
    // 获取 a_Position 变量在着色器程序中的位置,参考顶点着色器源码
    var aloc = gl.getAttribLocation(program, 'a_Position');
    // 将 gl.ARRAY_BUFFER 中的数据传入 aloc 表示的变量,即 a_Position
    gl.vertexAttribPointer(aloc, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(aloc);
    
  6. 向着色器传入矩阵时,是按列存款和储蓄的。可以相比一下 mmatrix 和矩阵转换一节中的模型矩阵(第 3 个)。

  7. 终极着色器总括出的 gl_Position 正是 CCV 中的坐标,比如最上边的终极(浅紫蓝)的 gl_Position 化成齐次坐标正是(0,0.5,0.5,1)。

  8. 向终点着色器传入的只是多少个顶峰的水彩值,而三角形表面包车型客车颜料渐变是由那四个颜色值内插出的。光栅化不仅仅会对 gl_Position 进行,还有只怕会对 varying 变量插值。

  9. gl.drawArrays()方法使得缓冲区进行绘图,gl.T奇骏IANGLES 内定绘制三角形,也足以更改参数绘制点、折线等等。

至于 ArrayBuffer 的详细新闻,能够参谋:

  • ArrayBuffer@MDN
  • 阮一峰的 ArrayBuffer 介绍
  • 张鑫旭的 ArrayBuffer 介绍

至于 gl.T悍马H2IANGLES 等任何绘制形式,可以参见下边那张图或那篇博文。

威尼斯手机娱乐官网 19

纵深检查评定

当四个外表重叠时,前边的模型会遮盖前面包车型大巴模型。例如那几个例子,绘制了多个交叉的三角形( varray 和 carray 的长短变为 18,gl.drawArrays 尾数参数变为 6)。为了轻松,那么些事例去掉了矩阵调换进程,直接向着色器传入 CCV 坐标。

威尼斯手机娱乐官网 20

威尼斯手机娱乐官网 21

终点着色器给出了 6 个终端的 gl_Position ,经过光栅化,片元着色器获得了 2X 个片元(假若 X 为各样三角形的像素个数),各类片元都离散的 x,y 坐标值,还应该有 z 值。x,y 坐标正是三角形在 Canvas 上的坐标,但借使有四个具有同等 x,y 坐标的片元同不常候出现,那么 WebGL 就能取 z 坐标值相当小的百般片元。

在深度检查实验此前,必得在绘制前拉开三个常量。否则,WebGL 就能够依据在 varray 中定义的逐个绘制了,前边的会覆盖后边的。

JavaScript

gl.enable(gl.DEPTH_TEST);

1
gl.enable(gl.DEPTH_TEST);

实际,WebGL 的逻辑是那样的:依次拍卖片元,假若渲染缓冲区(这里就是Canvas 了)的充裕与当前片元对应的像素还尚无绘制时,就把片元的颜料画到渲染缓冲区对应像素里,同不经常间把片元的 z 值缓存在另一个深度缓冲区的一致地点;假使当前缓冲区的呼应像素已经绘制过了,就去查看深度缓冲区中对应地方的 z 值,即使当前片元 z 值小,就重绘,不然就废弃当前片元。

WebGL 的那套逻辑,对明白蒙版(后边会说起)有点帮扶。

深度质量评定

当多个外表重叠时,前边的模子会隐蔽后边的模型。比方其一事例,绘制了多个交叉的三角( varray 和 carray 的长短变为 18,gl.drawArrays 最终叁个参数变为 6)。为了轻易,那几个例子去掉了矩阵调换进程,直接向着色器传入 CCV 坐标。

威尼斯手机娱乐官网 22

威尼斯手机娱乐官网 23

极限着色器给出了 6 个顶峰的 gl_Position ,经过光栅化,片元着色器获得了 2X 个片元(假如 X 为每一个三角形的像素个数),种种片元都离散的 x,y 坐标值,还应该有 z 值。x,y 坐标正是三角形在 Canvas 上的坐标,但一旦有五个具备同等 x,y 坐标的片元同期出现,那么 WebGL 就能够取 z 坐标值异常的小的丰裕片元。

在深度检验在此以前,必需在绘制前拉开多个常量。不然,WebGL 就能遵照在 varray 中定义的一一绘制了,后边的会覆盖前边的。

gl.enable(gl.DEPTH_TEST);

实际上,WebGL 的逻辑是这么的:依次拍卖片元,若是渲染缓冲区(这里正是Canvas 了)的老大与当下片元对应的像素还平素不绘制时,就把片元的颜料画到渲染缓冲区对应像素里,同一时候把片元的 z 值缓存在另八个纵深缓冲区的同壹地方;假诺当前缓冲区的照管像素已经绘制过了,就去查看深度缓冲区中对应地点的 z 值,若是当前片元 z 值小,就重绘,不然就屏弃当前片元。

WebGL 的那套逻辑,对理解蒙版(后边会谈起)有局地救助。

顶点索引

gl.drawArrays()是根据顶点的依次绘制的,而 gl.drawElements()能够令着色器以三个索引数组为顺序绘制顶点。举个例子本条例子。

威尼斯手机娱乐官网 24

此地画了七个三角,但只用了 5 个顶峰,有一个巅峰被多个三角共用。那时要求创立索引数组,数组的种种成分表示顶点的索引值。将数组填充至gl.ELEMENT_ARRAY,然后调用 gl.drawElements()。

JavaScript

var iarray = new Uint8Array([0,1,2,2,3,4]); var ibuffer = gl.createBuffer(gl.ARRAY_BUFFER, ibuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, iarray, gl.STATIC_DRAW);

1
2
3
4
var iarray = new Uint8Array([0,1,2,2,3,4]);
var ibuffer = gl.createBuffer(gl.ARRAY_BUFFER, ibuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, iarray, gl.STATIC_DRAW);

顶点索引

gl.drawArrays()是遵照顶点的一一绘制的,而 gl.drawElements()能够令着色器以贰个索引数组为顺序绘制顶点。比方其一例子。

威尼斯手机娱乐官网 25

此处画了八个三角形,但只用了 5 个极点,有三个极限被八个三角形共用。那时须要树立索引数组,数组的每一种成分表示顶点的索引值。将数组填充至gl.ELEMENT_ARRAY,然后调用 gl.drawElements()。

var iarray = new Uint8Array([0,1,2,2,3,4]);
var ibuffer = gl.createBuffer(gl.ARRAY_BUFFER, ibuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, iarray, gl.STATIC_DRAW);

本文由威尼斯手机娱乐官网发布于计算机知识,转载请注明出处:WebGL本事储备指南,手艺储备指南

上一篇:使用透明效果来自定义文件上传按钮控件样式, 下一篇:没有了
猜你喜欢
热门排行
精彩图文