仿射变换
对图形进行平移、旋转和缩放,
这样的操作称为 变换(transformations),
或 仿射变换(affine transformations)
平移
将点 p(x,y,z) 平移到 p’(x’,y’,z’),
在X轴、Y轴、Z轴三个方向平移的距离分别为:Tx,Ty, Tz ,
其中 Tz=0 。
x’ = x + Tx
y’ = y + Ty
z’ = z + Tz

平移是一个 逐顶点操作(per-vertex operation),
因此修改应当发生在 顶点着色器 。
Translated Triangle
TranslatedTriangle Code

1 |
|
1 | // 顶点着色器 |
齐次坐标
gl.uniform4f() 需要接收 齐次坐标,
齐次坐标共有 4个分量,
最后一个分量如果是 1.0, 表示前三个分量是 一个点的三维坐标。

旋转
为了描述一次旋转,必须指明以下3个条件:
- 旋转轴
- 旋转方向
- 旋转角度
右手法则旋转(right-hand-rule rotation)
也称 正旋转,
判断标准就是:右手握拳,拇指朝上指向z轴正方向,其余四指指向的方向就是旋转的正方向。

数学表达
点 p(x,y,z) 旋转 β 角度之后变为了点 p’(x’,y’,z’),
旋转是绕Z轴逆时针进行的。
设 o 为原点
设 r = op
设 α 为 op 与 x轴夹角
x’ = rcos( α + β ) = r(cosαcosβ - sinαsinβ) = xcosβ - ysinβ
y’ = rsin( α + β ) = r(sinαcosβ + sinβcosα) = ycosβ + xsinβ
z’ = z

依旧是由顶点着色器处理。
Rotated Triangle
RotatedTriangle Code

1 |
|
1 | let VSHADER_SOURCE = |
一些小问题
关于uniform变量值的计算位置问题
一般将uniform变量放在JS中算好再传递到shader中,
这样只需要计算一次,效率更高。
点操作符访问分量问题
在shader程序中,
无论是对 传入的变量 还是 gl变量,
都使用 点操作符 来访问分量。

弧度制参数问题
JS内置函数 Math.sin() 和 Math.cos()
都只接受 弧度制参数。
因此需要将 角度值参数 转换为 弧度制参数:
let radian = Math.PI * ANGLE / 180.0 ;
使用数组传入三角函数值
Vertex_Shader
1 | let VSHADER_SOURCE = |
传入uniform变量
1 | let u_CosBSinB = gl.getUniformLocation(gl.program, 'u_CosBSinB'); |
Rotated Triangle 升级版
蹦蹦床

1 | gl.uniform1f(u_sinB, Math.sin(currentAngle*Math.PI/180.0)); |