WebGL入门课程03-图形变换
[TOC]
九、WebGL变换
平移
- 平移是对顶点的每个分量加上对应轴上的平移距离
- 公式:
- x‘=x+Tx
- y’=y+Ty
- z’=z+Tz
缩放
- 缩放是对顶点的每个分量倍数放大或者缩小
vec4(x,y,z,w)=>vec4(x/w,y/w,z/w,1.0)
- 实际操作:改变w的
gl_Position.w=u_cha;
旋转
-
旋转需指明:旋转轴、旋转方向、旋转角度
-
公式:
- x’=xcosB-ysinB
- y’=xsinB+ycosB
- z’=z
十、WebGL矩阵变换
平移
缩放
旋转
注:在WebGL中矩阵以列为朱序
function translate(Tx, Ty, Tz) {
return new Float32Array([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
Tx, Ty, Tz, 1.0,
])
}
function scale(Tx, Ty, Tz) {
return new Float32Array([
Tx, 0.0, 0.0, 0.0,
0.0, Ty, 0.0, 0.0,
0.0, 0.0, Tz, 0.0,
0.0, 0.0, 0.0, 1.0,
])
}
function rotate(angle) {
let sinB = Math.sin(Math.PI * angle / 180.0);
let cosB = Math.cos(Math.PI * angle / 180.0);
return new Float32Array([
cosB, sinB, 0.0, 0.0,
-sinB, cosB, 0.0, 0.0,
0.0, 0.0, 1, 0.0,
0.0, 0.0, 0.0, 1.0,
])
}
十一、高级变换与动画基础-矩阵复合变换
- 变换要求:先平移后旋转
- 变换步骤:
- 将各个变换矩阵封装到Matrix.js中
- 着色器中定义uniform变量的变换矩阵
- 获取program中相关的uniform变量的位置
- 往变换矩阵中赋值
- 矩阵相乘:想先做哪一个操作就先乘哪一个,靠近原点坐标先做
十二、动画基础
- 动画的关键:不断擦除重绘,每次重绘轻微改变顶点的位置
- 动画关键的机制:
- 机制一,在每一个t时帆布调用同一个函数绘制
- 机制二,在每一次绘制之前,清除上次绘制的内容,并作出相关变换
- 关键函数
requestAnimationFrame(func)
cancelAnimationFrame(reqid)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动画</title>
<script src="lib.js"></script>
<script src="matrix.js"></script>
<style>
#web10 {
height: 500px;
width: 500px;
}
</style>
</head>
<body>
<canvas id="web10"></canvas>
<script>
let canvas = document.querySelector('#web10');
let gl = canvas.getContext('webgl');
let VERTEX_SHADER = '' +
'attribute vec4 a_pos;' +
'uniform mat4 u_translate;' +
'uniform mat4 u_rotate;' +
'uniform mat4 u_scale;' +
'void main(){' +
'gl_Position=u_scale*u_rotate*u_translate*a_pos;' +
'}';//右侧的先执行
let FRAG_SHADER = '' +
'void main(){' +
'gl_FragColor=vec4(1.0,0.5,0.0,1.0);' +
'}';
let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
let dataVer = new Float32Array([
-0.3, 0.0,
0.0, 0.3,
0.3, 0.0
]);
bufferInit(gl, dataVer, 'a_pos', program);
gl.clearColor(0.6, 0.0, 0.3, 1.0);
let u_translate = gl.getUniformLocation(program, 'u_translate');
let u_rotate = gl.getUniformLocation(program, 'u_rotate');
let u_scale = gl.getUniformLocation(program, 'u_scale');
let x = 0.0, y = 0.0, angle = 4.0, a = 1.0, b = 1.0;
function animation() {
x += 0.01;
y += 0.01;
angle += 5;
a -= 0.01;
b -= 0.01;
gl.uniformMatrix4fv(u_translate, false, translate(x, y, 0.0));
gl.uniformMatrix4fv(u_rotate, false, rotate(angle));
gl.uniformMatrix4fv(u_scale, false, scale(a, b, 1.0));
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function run() {
animation();
let act = requestAnimationFrame(run);
if (a < 0) {
cancelAnimationFrame(act);
alert("我一定会回来的!")
}
}
run();
</script>
</body>
</html>