标签:-418 公式 相加 main 编程指南 readonly tty 2.3 UI
在图形学中,特别是涉及到3D的时候,矩阵变换起着非常重要的作用。在实际使用的过程当中,通常每一帧画面可能都会涉及到成千上万个顶点的坐标变换,如果没有矩阵变换计算,一个是计算复杂,一个是难以达到我们想要的计算效率。本小节将介绍通过矩阵计算来实现基本的图形变换。
矩阵是一种多个数据集合的表示方式,定义为:由 m × n 个数
矩阵的存在主要是由于它的运算,下面来简单看一下:
可以看到,矩阵加法就是对应的位置的数值相加。
可以看到,矩阵减法就是对应的位置的数值相减。
乘法规则示意图如下:
在矩阵乘法中,注意,左边矩阵的列数必须等于右边矩阵的行数。
把矩阵的行和列位置进行互换的矩阵,称为矩阵的转置。
矩阵有很多的特性以及计算定律,这里只是介绍一些基本概念,以后需要用到再继续填充本小节的内容。
之前我们学习过了基本的图形变换,知道比如要平移一个三角形,实际上只要对三角形三个顶点都进行平移,重新绘制出来的三角形就是平移后的三角形。在3D的世界里,我们会通过对顶点的各种运算,然后重绘,来得到各种图形的基本变换。基本变换包括平移、旋转和缩放,然而从之前的学习中可以发现,每一种基本的变换都使用了不同的公式,形式不一,这达不到一种很好的效果,特别对硬件而言,要针对多种变换去优化代价是比较大的。矩阵的出现恰好解决了这个难题,通过矩阵运算,使各种基本变换(包括以后学习的各类高级变换)达成了一致的计算模型,使得硬件可以针对矩阵运算模型进行优化。
之前通过推导,得到了点的旋转公式如下:
通过旋转矩阵的推导,对于平移操作,如果我们也想找到相应的3*3矩阵来进行平移计算,先来看看
该4*4矩阵的乘法表示如下:
我们发现平移需要用到4*4,而之前旋转矩阵用到的是3*3矩阵,这显然还不太统一,于是,我们想办法把3*3的旋转矩阵转为4*4的旋转矩阵。经过前面的学习,我们很容易得出如下方程组:
经过前面的学习,我们很容易得到求缩放矩阵相关方程组:
前面讲了那么多的矩阵变换,我们尝试使用矩阵来实现平移效果。首先来看一下顶点着色器代码:
// 顶点着色器代码(决定顶点的位置、大小、颜色)
var VSHADER_SOURCE =
‘attribute vec4 a_Position;\n‘ +
‘uniform mat4 u_xformMatrix;\n‘ +
‘void main() {\n‘ +
‘ gl_Position = u_xformMatrix * a_Position;\n‘ + //webgl内置支持矩阵乘法
‘ gl_PointSize = 10.0;\n‘ + // 设置顶点的大小
‘}\n‘;
以上定义了一个叫u_xformMatrix的4*4矩阵变量,然后与顶点进行了相乘,得到最后的顶点坐标。
接着来看一下矩阵的定义:
// webgl按列的模式来读,所以定义矩阵时要使用转置矩阵
var xformMatrix = 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
]);
var u_xformMatrix = context.getUniformLocation(context.program, ‘u_xformMatrix‘);
context.uniformMatrix4fv(u_xformMatrix , false , xformMatrix);
最终得到的效果图如下:
矩阵变换实现三角形的旋转和缩放的原理是一样的,只需要修改矩阵的定义即可,大家可以尝试一下。
前面讲到的矩阵变换都是针对单个变换的,如果想要对一个三角形同时进行平移和缩放,该如何处理呢?
如果仔细想想,不难得到如下等式:
根据矩阵乘法结合律,又可得:
我们来看个多重变换的例子,把一个三角形平移后再进行缩放,先来看下顶点着色器代码:
// 顶点着色器代码(决定顶点的位置、大小、颜色)
var VSHADER_SOURCE =
‘attribute vec4 a_Position;\n‘ +
‘uniform mat4 u_translateMatrix;\n‘ +
‘uniform mat4 u_scaleMatrix;\n‘ +
‘void main() {\n‘ +
‘ gl_Position = u_scaleMatrix * u_translateMatrix * a_Position;\n‘ +
‘ gl_PointSize = 10.0;\n‘ + // 设置顶点的大小
‘}\n‘;
可以看到,顶点着色器先计算两个变换矩阵相乘,最后再乘以顶点坐标。
变换矩阵的赋值如下所示:
var Tx = 0.5 , Ty = 0.5 , Tz = 0.0;
// 按列方向读取,定义时使用矩阵转置
var translateMatrix = 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
]);
var u_translateMatrix = context.getUniformLocation(context.program, ‘u_translateMatrix‘);
context.uniformMatrix4fv(u_translateMatrix , false , translateMatrix);
// 缩小一半
var Sx = Sy = Sz = 0.5;
// 按列方向读取,定义时使用矩阵转置
var scaleMatrix = new Float32Array([
Sx , 0.0 , 0.0 , 0.0,
0.0 , Sy , 0.0 , 0.0,
0.0 , 0.0 , Sz , 0.0,
0.0 , 0.0 , 0.0 , 1.0
]);
var u_scaleMatrix = context.getUniformLocation(context.program, ‘u_scaleMatrix‘);
context.uniformMatrix4fv(u_scaleMatrix , false , scaleMatrix);
最终效果图如下:
我们在顶点着色器中计算了两个矩阵相乘,实际上,三角形三个顶点我们重复计算了三遍,如果有一万个顶点,这样子处理是非常浪费时间的,更高效的做法是先计算好两个矩阵相乘,然后顶点着色器只定义一个最终的矩阵即可,我们再来看看之前定义的矩阵:
本篇探讨了一下基本的矩阵变换,这对于认识到矩阵的巨大用处是非常重要的。在3D的世界里,其实就是各种矩阵的计算,然后得到变换后的顶点的坐标,最后再绘制出来。知道了矩阵的使用原理,为以后更加复杂的投影变换打下基础。
标签:-418 公式 相加 main 编程指南 readonly tty 2.3 UI
原文地址:http://blog.csdn.net/yanyan19880509/article/details/57411916