Skip to content

Commit ed706ed

Browse files
committed
高级变换与动画基础
变换
1 parent 3bd1850 commit ed706ed

File tree

3 files changed

+171
-1
lines changed

3 files changed

+171
-1
lines changed

docs/WebGL/Chapter3.md

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,174 @@ function initVertexBuffers(gl) {
204204
| Matrix4.rotate(angle,x,y,z) | 将Matrix4实例乘以一个旋转变换矩阵(该旋转矩阵旋转的角度为angle,旋转轴为<br/>(x,y,z)。旋转轴(x,y,z)无须归一化),所得的结果还存储在Matrix4中 |
205205
| Matrix4.scale(x,y,z) | 将Matrix4实例乘以一个缩放变换矩阵(该缩放矩阵在三个轴上的缩放因子分别为x,y和z),所得的结果还储存在Matrix4中 |
206206
| Matrix4.set(m) | 将Matrix4实例设置为m,m必须也是一个Matrix4实例 |
207-
| Matrix4.elements | 类型化数组(Float32Array)包含了Matrix4 实例的矩阵元素 |
207+
| Matrix4.elements | 类型化数组(Float32Array)包含了Matrix4 实例的矩阵元素 |
208+
209+
**单位阵在矩阵乘法中的行为,就像数字1在乘法中的行为一样。将一个矩阵乘以单位阵,得到的结果和原矩阵完全相同。在单位阵中,对角线上的元素为1.0,其余的元素为0.0**
210+
211+
包含set前缀的方法会根据参数计算处变换矩阵,然后将变换矩阵写入到自身中;不含set前缀的方法,会先根据参数计算出变换矩阵,然后将自身与刚刚计算得到的变换矩阵相乘,然后把最终得到的结果再写入到Matrix4对象中
212+
213+
## 复合变换
214+
平移 旋转
215+
216+
### 先平移后旋转
217+
218+
平移后的坐标 = 平移矩阵 * 原始坐标
219+
220+
旋转后的坐标 = 旋转矩阵 * 平移后的坐标
221+
222+
即:
223+
224+
平移后旋转的坐标 = 旋转矩阵 * (平移矩阵 * 原始坐标) = (旋转矩阵 * 平移矩阵) * 原始坐标
225+
226+
`javascript`中,计算 `旋转矩阵` * `平移矩阵`,将得到的矩阵传入顶点着色器。这样就可以把多个变换复合起来。一个模型可能经过了多次变换
227+
将这些变换全部复合成一个等效的变换,就得到了`模型变换(model transformation)` 或称`建模变换(modeling transformation)`,相应地,模型变换
228+
的矩阵称为`模型矩阵(model matrix)`
229+
230+
```js
231+
const VSHADER_SOURCE =
232+
'attribute vec4 a_Position;\n' +
233+
'uniform mat4 u_xformMatrix;\n' + // [!code --]
234+
'uniform mat4 u_ModelMatrix;\n' + // [!code ++]
235+
'void main() {\n' +
236+
'gl_Position = u_xformMatrix * a_Position;\n' + // [!code --]
237+
'gl_Position = u_ModelMatrix * a_Position;\n' + // [!code ++]
238+
// 'gl_PointSize = 10.0;\n' +
239+
'}\n'
240+
const FSHADER_SOURCE =
241+
' void main() {\n' +
242+
'gl_FragColor = vec4(1.0, 1.0, 0.0,1.0);\n' +
243+
'}\n'
244+
245+
246+
var ANGLE = 90.0
247+
248+
function main() {
249+
var canvas = document.getElementById('webgl')
250+
var gl = getWebGLContext(canvas)
251+
if (!gl) {
252+
console.error('Failed to get the rendering context for WebGL')
253+
return;
254+
}
255+
256+
// 初始化着色器
257+
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
258+
console.error('Failed to initialize shaders.')
259+
return;
260+
}
261+
262+
// 设置顶点着色器
263+
var n = initVertexBuffers(gl);
264+
265+
if (n < 0) {
266+
console.error('Failed to set the positions of the vertices')
267+
return;
268+
}
269+
270+
var u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix') // [!code --]
271+
272+
var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix') // [!code ++]
273+
274+
var modelMatrix = new Matrix4()
275+
276+
xformMatrix.setRotate(ANGLE, 0, 0, 1) // [!code --]
277+
278+
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix.elements) // [!code --]
279+
280+
var Tx = 0.5 // [!code ++]
281+
282+
283+
modelMatrix.setRotate(ANGLE, 0, 0, 1) // [!code ++]
284+
modelMatrix.translate(Tx, 0.5, 1) // [!code ++]
285+
286+
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements) // [!code ++]
287+
288+
289+
290+
// // 获取attribut变量的存储位置
291+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
292+
//
293+
// var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')
294+
if (a_Position < 0) {
295+
console.error('Failed to get the storage location of a_Position')
296+
return;
297+
}
298+
//
299+
// canvas.onmousedown = function (ev) {click(ev, gl, canvas, a_Position, u_FragColor)}
300+
301+
302+
// gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0)
303+
304+
// 设置canvas背景色
305+
gl.clearColor(0.0, 0.0, 0.0, 1.0)
306+
307+
// 清空canvas
308+
gl.clear(gl.COLOR_BUFFER_BIT);
309+
310+
// 绘制三个点
311+
gl.drawArrays(gl.TRIANGLE_FAN, 0, n)
312+
313+
}
314+
315+
function initVertexBuffers(gl) {
316+
var vertices = new Float32Array([
317+
-0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
318+
])
319+
var n = 4 // 点的个数
320+
321+
// 创建缓冲区对象
322+
var vertexBuffer = gl.createBuffer();
323+
if (!vertexBuffer) {
324+
console.error('Failed to create the buffer object')
325+
return -1;
326+
}
327+
328+
// 将缓冲区对象绑定到目标
329+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
330+
331+
// 向缓冲区对象中写入数据
332+
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
333+
334+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
335+
336+
// 将缓冲区对象分配给a_Position变量
337+
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
338+
339+
// 连接a_Position变量与分配给它的缓冲对象
340+
gl.enableVertexAttribArray(a_Position)
341+
return n
342+
}
343+
```
344+
345+
modelMatrix.setRotate(ANGLE, 0, 0, 1) // 设置模型矩阵为旋转矩阵
346+
modelMatrix.translate(Tx, 0, 0) // 将模型矩阵乘以平移矩阵
347+
348+
**先平移后旋转的顺序与构造模型矩阵 旋转矩阵 * 平移矩阵 的顺序是相反的,这是因为变换矩阵最终要与三角形的三个顶点的原始坐标矢量相乘**
349+
350+
351+
**平移旋转**
352+
353+
```js
354+
// 平移旋转
355+
modelMatrix.setRotate(ANGLE, 0, 0, 1)
356+
modelMatrix.translate(Tx, 0.5, 1)
357+
```
358+
359+
![效果图](./images/translateAndRotate.png)
360+
361+
362+
**旋转平移**
363+
```js
364+
// 旋转平移
365+
modelMatrix.setTranslate(Tx, 0.5, 1)
366+
modelMatrix.rotate(ANGLE, 0, 0, 1)
367+
```
368+
369+
![效果图](./images/rotateAndTranslate.png)
370+
371+
372+
**平移个旋转的次序不一样 导致的结果页不一样**
373+
374+
375+
## 动画
376+
377+
将矩阵变换运用到动画图形中去
21.2 KB
Loading
20 KB
Loading

0 commit comments

Comments
 (0)