WebGL通过一种称作纹理单元(texture unit)的机制来同时使用多个纹理。每个纹理单元有一个单元编号来管理一张纹理图像。即使你的程序只需要一张纹理图像,也得为其指定一个纹理单元。系统支持的纹理单元个数取决于硬件和浏览器的WebGL实现,但是在默认情况下,web GL至少支持8个纹理单元,一些其他的系统支持的个数更多。内置的变量gl.TEXTURE0、gl.TEXTURE1、gl.TEXTURE2。。。。gl.TEXTURE7各表示一个纹理单元。
顶点着色器与片元着色器通信
通常我们在顶点着色器中声明一个attribute变量a_Color用以接受颜色,然后再用varying(只能是float以及vec2,vec3,vec4,mat2,mat3和mat4)声明变量v_Color,该变量负责将颜色值传给着色器,
1 | attribute vec4 a_Color; |
那么片元着色器如何接收到这个变量呢,很简单,同样声明一个
1 | varying vec4 v_Color; |
这是因为在WebGL中,如果顶点着色器和片元着色器同时有类型和命名相同的varying变量,那么顶点着色器会自动地将该变量的值传入片元着色器。
Cesium中的矩阵变换
上一篇学习了WebGL中的矩阵变换变换矩阵(Transformation-matrix)详解,我们推演出旋转、平移、缩放矩阵,并通过代码实现。而在Cesium中于此类似,并且提供了Cesium.Matrix2、Cesium.Matrix3、Cesium.Matrix4类及其属性方法。
这里,我们以Cesium.Matrix4为例
正常情况下,我们可以通过tileset.root.transform获取模型本身的模型矩阵,这个即存在3DTile中的tileset.json文件中
那么在Cesium中具体如何操作使用变换矩阵呢?
以调整模型位置为例
一、Cesium中的平移
有两种调整方式
(1)矩阵点乘法
1 | let modelMatrix = tileset.root.transform; |
(2)直接设置
1 | let modelMatrix = tileset.root.transform; |
二、Cesium中的旋转
1 | let modelMatrix = tileset.root.transform; |
三、Cesium中的缩放
1 | const scale = 1.1; |
四、综述
Cesium中的平移缩放旋转MxTxSxR涉及到的矩阵变换如下;
1 | // 平移 |
变换矩阵(Transformation matrix)详解
当我们对一个图形进行平移再旋转,一般流程是需要重新求取一个新的等式,然后实现一个新的着色器,这样很不好。
好在我们可以使用另一个数学工具—变换矩阵(Transformation matrix)来完成这项工作。变换矩阵非常适合操作计算机图形。
一、旋转矩阵
当p按照右手法则逆时针旋转β
p点的坐标计算为:
p`点坐标
分解后,即
基于第一个公式,消掉r和α,得:
通过以下矩阵相乘可以表示该过程
综合以上两个公式:
我们可以令
a=cosβ,b=-sinβ,c=0,d=sinβ,e=cosβ,f=0,g=0,h=0,i=1,
可得:
二、平移矩阵
一般平移矩阵计算为:
相乘得到:
比较以下等式
我们可以令:
a=1,b=0,c=0,d=Tx,
e=0,f=1,g=0,h=Ty,
i=0,j=0,k=1,l=Tz,
m=0,n=0,o=0,p=1,
可得:
三、缩放
假设X轴、Y轴、Z轴缩放因子Sx,Sy,Sz,那么有:
即有缩放变换矩阵:
四、旋转+平移+缩放
至此,我们已经推演出一个旋转矩阵和一个平移矩阵、一个缩放矩阵,但是我们发现旋转矩阵是3x3,平移缩放矩阵是4x4, 于是需要将旋转矩阵转变为4x4矩阵,我们知道最后一个分量w的加和结果应为1
所以:
所以在程序中定义一个旋转+平移+缩放矩阵,可以按照以下写:
注意WebGL中矩阵是列主序的,即为上面矩阵的转置
1 | const canvas=document.getElementById('webgl'); |
gl.drawArrays的使用
缓冲区对象是WebGL系统中的一块存储区,可以在里面存储想要绘制的所有顶点数据,通过创建缓冲区,就能够一次性地向顶点着色器传入多个顶点的attribute变量的数据。
gl.drawArrays(mode, first, count)
1、modes指的是绘制方式,gl.POINTS、gl.LINES、gl.LINE_STRIP、gl.LINE_LOOP、gl.TRIANGLES、gl.TRIANGLES_STRIP、gl.TRIANGLE_FAN;
具体使用如下表


2、first指的是从哪一个顶点开始绘制;
3、count指的是绘制需要多少个顶点。
关于bash中的2>&1 &理解
经常运行一些python脚本或者jar包,如果直接运行python *.py,或者 java -jar *.jar,再进行其他操作,需要终止运行,所以应该是后台运行。
这也就经常看到这样的句式:
1 | nohup python *.py > nohup.log 2>&1 & |
1、开始的nohup(no hang up, 不挂起),用于系统后台不挂断的运行命令;
2、中间的python *.py我们好理解,就是运行脚本;
3、> nohup.log 意思将新建nohup.log文件,并将运行日志写到该文件中,我们可以使用>>,表示追加日志内容;
4、bash中0,1,2分别表示STDIN_FILENO(标准输入),STDOUT_FILENO( 标准输出),STDERR_FILENO(标准错误),输入输出可以重定向,如cat < text.c将test.c重定向为cat命令的输入源,输出重定向就是将指定具体的输出目标以替换默认的标准输出。默认输入只有一个(0,STDIN_FILENO),而默认输出有两个(标准输出1,STDOUT_FILENO,标准错误输出2,STDERR_FILENO),因此输出的错误信息会被输出到2,而普通信息会输出到1,但我们希望在一个终端下看到所有的信息,那么综上就应该是2>1,而2>&1中&是为了bash将1解释成标准输出而不是文件1,至于2>&1 &中最后一个&则是让bash在后台运行。
类型化数组
为了绘制三维图形,WebGL通常需要同时处理大量相同类型的数据,例如顶点的坐标和颜色数据。为了优化性能,WebGL为每种基本数据类型引入了一种特殊的数组(类型化数组)。浏览器事先知道数组中的数据类型,所以处理起来也更加有效率。

注意:
- 类型化数组不支持push,pop方法;
- 类型化数组初始化唯一方法是new,如 new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]);
- 另外,可以通过定义长度初始化一个数组 new Float32Array(4)
缓冲区对象工作流程
1 | 1、创建缓冲区对象(gl.createBuffer()); |


WebGL缓冲区(buffer object)对象
WebGL 提供了一种很方便的机制,即缓冲区对象(buffer obiect),它可以一次性地向着色器传人多个顶点的数据。
缓冲区对象是 WebGL 系统中的一块内存区域,我们可以一次性地向缓冲区对象中填充大量的顶点数据,然后将这些数据保存在其中,供顶点着色器使用。
