Skip to content

Commit 3bd1850

Browse files
committed
高级变换与动画基础
Matrix4 对象
1 parent 3f7a606 commit 3bd1850

File tree

2 files changed

+209
-1
lines changed

2 files changed

+209
-1
lines changed

docs/.vitepress/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ module.exports = {
171171
text: 'WebGL',
172172
items: [
173173
{ text: '第一章', link: '/WebGL/' },
174-
{ text: '第二章', link: '/WebGL/Chapter2'}
174+
{ text: '第二章', link: '/WebGL/Chapter2'},
175+
{ text: '第三章', link: '/WebGL/Chapter3'}
175176
]
176177
}
177178
},

docs/WebGL/Chapter3.md

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
---
2+
editLink: false
3+
outline: deep
4+
outlineText: "33"
5+
---
6+
7+
# 高级变换与动画基础
8+
9+
1. 学习使用一个矩阵变换库,该库封装了矩阵运算的数学细节
10+
2. 快速上手使用矩阵库,对图形进行复合变换
11+
3. 在该矩阵库的帮助下,实现简单的动画效果
12+
13+
## 平移 然后旋转
14+
15+
平移、旋转、缩放等变换操作都可以用一个 4x4的矩阵表示。使用矩阵库可以简化编程(手动计算每个矩阵很耗费时间)
16+
17+
`Matrix4`对象表示一个4x4的矩阵。该对象内部使用类型化数组`Float32Array`来存储矩阵的元素
18+
19+
**WebGL和OpenGL一样,矩阵元素是按列主序存储在数组中的**
20+
21+
`mat4``vec4` 的区别:
22+
23+
1. 定义和结构
24+
- mat4:
25+
- 表示一个**4x4的矩阵**,用于进行各种线性变换,如平移、旋转、缩放和透视投影
26+
- 包含16个元素(4行4列),通常以列优先的方式储存
27+
- 如:
28+
```smalltalk
29+
| m00 m01 m02 m03 |
30+
| m10 m11 m12 m13 |
31+
| m20 m21 m22 m23 |
32+
| m30 m31 m32 m33 |
33+
```
34+
- vec4:
35+
- 表示一个**4维向量**,通常用于表示点、方向或颜色
36+
- 包含4个元素,通常是x,y,z,w
37+
- 如:
38+
```
39+
| x |
40+
| y |
41+
| z |
42+
| w |
43+
```
44+
2. 用途
45+
- mat4
46+
- 用于处理变换和投影。在图形渲染中,模型变换、视图变换和投影变换通常都会用到mat4
47+
- 可以与vec4进行相乘,以应用变换
48+
```glsl
49+
vec4 transformedPositon = modelMatrix * originalPosition
50+
```
51+
- vec4
52+
- 用于表示物体的位置、颜色或光照等特征。
53+
- 位置:在3D空间中的点(通常w分量用于齐次坐标)
54+
- 颜色:RGBA颜色值(红、绿、蓝、透明度)
55+
- 也可以与其他向量进行运算
56+
```glsl
57+
vec4 color = vec4(1.0, 0.5, 0,0, 1.0)
58+
```
59+
3. 运算
60+
- 矩阵和向量的运算:
61+
mat4和vec4可以结合使用,通过矩阵和向量的乘法进行变换。矩阵乘法会改变向量的坐标,应用变换效果
62+
- 向量运算:
63+
vec4之间可以进行加减、点积、叉积等运算
64+
65+
**mat4是一种用于表示和操作4x4矩阵的类型,主要用于变换**
66+
**vec4是一种表示4维向量的类型,主要用于表示颜色、位置和方向**
67+
68+
69+
**`gl.uniformMatrix4fv(location, transpose, array)`**
70+
71+
将*array*表示的4x4矩阵分配给由`location`指定的`uniform`变量
72+
73+
| 参数 | 描述 |
74+
|-------------------|------------------------------|
75+
| location | uniform变量的存储位置 |
76+
| Transpose | 在WebGL中必须指定为false |
77+
| array | 带传输的类型化数组,4x4矩阵按列主序存储在其中 |
78+
| 返回值 | 无 |
79+
| 错误 | 描述 |
80+
| INVALID_OPERATION | 不存在当前程序对象 |
81+
| INVALID_VALUE | transpose不为false,或者数组的长度小于16 |
82+
83+
```js
84+
const VSHADER_SOURCE =
85+
'attribute vec4 a_Position;\n' +
86+
'uniform float u_CosB, u_SinB;\n' + // [!code --]
87+
'uniform mat4 u_xformMatrix;\n' + // [!code ++]
88+
'void main() {\n' +
89+
'gl_Position.x = a_Position.x * u_CosB - a_Position.y * u_SinB;\n' + // [!code --]
90+
'gl_Position.y = a_Position.x * u_SinB + a_Position.y * u_CosB;\n' + // [!code --]
91+
'gl_Position.z = a_Position.z;\n' + // [!code --]
92+
'gl_Position.w = 1.0;\n' + // [!code --]
93+
'gl_Position = u_xformMatrix * a_Position;\n' + // [!code ++]
94+
'}\n'
95+
const FSHADER_SOURCE =
96+
' void main() {\n' +
97+
'gl_FragColor = vec4(1.0, 1.0, 0.0,1.0);\n' +
98+
'}\n'
99+
100+
101+
var ANGLE = 90.0
102+
103+
function main() {
104+
var canvas = document.getElementById('webgl')
105+
var gl = getWebGLContext(canvas)
106+
if (!gl) {
107+
console.error('Failed to get the rendering context for WebGL')
108+
return;
109+
}
110+
111+
// 初始化着色器
112+
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
113+
console.error('Failed to initialize shaders.')
114+
return;
115+
}
116+
117+
// 设置顶点着色器
118+
var n = initVertexBuffers(gl);
119+
120+
if (n < 0) {
121+
console.error('Failed to set the positions of the vertices')
122+
return;
123+
}
124+
125+
var radian = Math.PI * ANGLE / 180.0; // [!code --]
126+
var conB = Math.cos(radian); // [!code --]
127+
var sinB = Math.sin(radian); // [!code --]
128+
129+
var u_CosB = gl.getUniformLocation(gl.program, 'u_CosB'); // [!code --]
130+
var u_SinB = gl.getUniformLocation(gl.program, 'u_SinB'); // [!code --]
131+
132+
gl.uniform1f(u_CosB, conB) // [!code --]
133+
gl.uniform1f(u_SinB, sinB) // [!code --]
134+
135+
var u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix') // [!code ++]
136+
137+
var xformMatrix = new Matrix4() // [!code ++]
138+
xformMatrix.setRotate(ANGLE, 0, 0, 1) // [!code ++]
139+
140+
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix.elements) // [!code ++]
141+
142+
143+
144+
// // 获取attribut变量的存储位置
145+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
146+
//
147+
// var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')
148+
if (a_Position < 0) {
149+
console.error('Failed to get the storage location of a_Position')
150+
return;
151+
}
152+
153+
// 设置canvas背景色
154+
gl.clearColor(0.0, 0.0, 0.0, 1.0)
155+
156+
// 清空canvas
157+
gl.clear(gl.COLOR_BUFFER_BIT);
158+
159+
// 绘制三个点
160+
gl.drawArrays(gl.TRIANGLE_FAN, 0, n)
161+
162+
}
163+
164+
function initVertexBuffers(gl) {
165+
var vertices = new Float32Array([
166+
-0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
167+
])
168+
var n = 4 // 点的个数
169+
170+
// 创建缓冲区对象
171+
var vertexBuffer = gl.createBuffer();
172+
if (!vertexBuffer) {
173+
console.error('Failed to create the buffer object')
174+
return -1;
175+
}
176+
177+
// 将缓冲区对象绑定到目标
178+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
179+
180+
// 向缓冲区对象中写入数据
181+
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
182+
183+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
184+
185+
// 将缓冲区对象分配给a_Position变量
186+
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
187+
188+
// 连接a_Position变量与分配给它的缓冲对象
189+
gl.enableVertexAttribArray(a_Position)
190+
return n
191+
}
192+
193+
```
194+
195+
`Matrix4` 对象所支持的方法和属性
196+
197+
| 方法和属性名称 | 描述 |
198+
|--------------------------------|-------------------------------------------------------------------------------------------|
199+
| Matrix4.setIdentity() | 将Matrix4实例初始化为单位阵 |
200+
| Matrix4.setTranslate(x,y,z) | 将Matrix4实例设置为平移变换矩阵,在x轴上平移的距离为x,在y轴<br/>上平移的距离为y,在z轴上平移的距离为在 |
201+
| Matrix4.setRotate(angle,x,y,z) | 将Matrix4实例设置为旋转变换矩阵,旋转的角度为angle,旋转轴为(x,y,z)。<br/>旋转轴(x,y,z)无须归一化 |
202+
| Matrix4.setScale(x,y,z) | 将Matrix4实例设置为缩放变换矩阵,在三个轴上的缩放因子分别为x,y和z |
203+
| Matrix4.translate(x,y,z) | 将Matrix4实例乘以一个平移变换矩阵(该平移矩阵在x轴上平移的距离为x,在y轴<br/>上平移的距离为y,在z轴上平移的距离为z),所得的结果还储存在Matrix4中 |
204+
| Matrix4.rotate(angle,x,y,z) | 将Matrix4实例乘以一个旋转变换矩阵(该旋转矩阵旋转的角度为angle,旋转轴为<br/>(x,y,z)。旋转轴(x,y,z)无须归一化),所得的结果还存储在Matrix4中 |
205+
| Matrix4.scale(x,y,z) | 将Matrix4实例乘以一个缩放变换矩阵(该缩放矩阵在三个轴上的缩放因子分别为x,y和z),所得的结果还储存在Matrix4中 |
206+
| Matrix4.set(m) | 将Matrix4实例设置为m,m必须也是一个Matrix4实例 |
207+
| Matrix4.elements | 类型化数组(Float32Array)包含了Matrix4 实例的矩阵元素 |

0 commit comments

Comments
 (0)