上一篇基本复习了一下顶点着色器、片段着色器,能绘制出最基本的带纹理的二维图片。接下来就该介绍三维是怎么一个过程~
简单变换
矩阵基础知识
矩阵是什么?
下面这个就是一个2X3矩阵,图片其实可以认为是这么一个矩阵,里面的元素是rgb像素
矩阵的运算
矩阵拥有和数值一样的加减乘除运算。
加(减)法(以下分别是跟标量和跟矩阵的加法):
矩阵乘法:
和数值的乘法
矩阵相乘
缩放
假设向量v=(3,2) ,我们可以把向量沿着x轴缩放0.5,沿着y轴缩放2倍,得到的s如下图所示
可以定义空间的缩放举证如下
平移
旋转
9
任意角度旋转(Rx,Ry,Rz)包含任意旋转轴
矩阵的组合
这个就是注意旋转平移的先后顺序!!!!
矩阵计算的代码可以结合后面介绍的相机计算代码一起放在同一个util文件中
三维系统介绍
我们在观察实际的物体的时候,都是有一个透视效果,也即是近大远小。比如下图所示,实际的轨道其实是2个平行线,但是视觉效果在远方会相交。
相机
首先我们先看一些材料里常见的计算公式。
如何去理解这个公式
Mprojection 是投影矩阵:
实际我们能观察到的内容,是有一个限制区域的,如下图所示
能观察到的物体应该是在near plane和far plane所夹的梯形区域内。比如上图中的蓝色小矩形体就不能被摄像头观察到。
通过FOV角度、视角宽高比、近远距离可以定量描述这个区域
通常用到的函数如下,第一个参数是FOV角度,第二个参数是宽高比,第三个参数是近距离,第四个参数是远距离。
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
Mview 是观察矩阵:
简单来说就是这个摄像机的位置姿态描述。如下图所示
数学的描述就是look at 矩阵,实际的计算函数如下
glm::mat4 view;
view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
第一个是位置向量(上图的图1),第二个是定义相机看向的方向(上图的图2),第三个是定义摄像机朝上的向量(上图的图3)
Mmodel 是模型矩阵:
定义矩阵平移旋转等变换
Vlocal 是模型顶点数据:
这就是模型数据,后面会写这个数据怎么读取
下面是矩阵计算的具体代码:
/*---该文档主要用于数组计算---*/
#include <math.h>
#define PI 3.14159265f
//设置单位矩阵
void setone(float *matrix)
{
*(matrix + 0) = 1;
*(matrix + 1) = 0;
*(matrix + 2) = 0;
*(matrix + 3) = 0;
*(matrix + 4) = 0;
*(matrix + 5) = 1;
*(matrix + 6) = 0;
*(matrix + 7) = 0;
*(matrix + 8) = 0;
*(matrix + 9) = 0;
*(matrix + 10) = 1;
*(matrix + 11) = 0;
*(matrix + 12) = 0;
*(matrix + 13) = 0;
*(matrix + 14) = 0;
*(matrix + 15) = 1;
}
//向量归一化
void normalize(float *vector)
{
float matrix = pow(*(vector + 0), 2) + pow(*(vector + 1), 2) + pow(*(vector + 2), 2);
matrix = pow(matrix, 0.5);
*(vector + 0) = *(vector + 0) / matrix;
*(vector + 1) = *(vector + 1) / matrix;
*(vector + 2) = *(vector + 2) / matrix;
}
//投影矩阵
/*
float projection[4][4];
profection(45.0f, 800.0f / 800.0f, 0.1f, 100.0f, *projection);
*/
void profection(float angle, float ar, float zNear, float zFar,float *matrix)
{
float zRange = zFar - zNear;
float tanHalfFOV = tan(PI * angle / (float)360);
//float tanHalfFOV = tan(angle);
*(matrix + 0) = 1.0f / (ar * tanHalfFOV);
*(matrix + 1) = 0;
*(matrix + 2) = 0;
*(matrix + 3) = 0;
*(matrix + 4) = 0;
*(matrix + 5) = 1.0f / tanHalfFOV;
*(matrix + 6) = 0;
*(matrix + 7) = 0;
*(matrix + 8) = 0;
*(matrix + 9) = 0;
*(matrix + 10) = (-zNear - zFar) / zRange;
*(matrix + 11) = -1;
*(matrix + 12) = 0;
*(matrix + 13) = 0;
*(matrix + 14) = -2.0f * zFar * zNear / zRange;
*(matrix + 15) = 0;
}
//绕任意轴旋转角度
/*
float matrix[4][4];
setone(*matrix);
float vector[3] = { 1.0f,1.0f,1.0f };
rotate(*matrix, angle, vector);
*/
void rotate(float *matrix, float angle, float *vector)
{
float a = PI * angle / (float)180;
float c = cos(a);
float s = sin(a);
normalize(vector);
float tmp[4][4];
tmp[0][0] = (*(vector + 0))*(*(vector + 0))*(1 - c) + c;
tmp[0][1] = (*(vector + 0))*(*(vector + 1))*(1 - c) + (*(vector + 2))*s;
tmp[0][2] = (*(vector + 0))*(*(vector + 2))*(1 - c) - (*(vector + 1))*s;
tmp[0][3] = 0;
tmp[1][0] = (*(vector + 0))*(*(vector + 1))*(1 - c) - (*(vector + 2))*s;
tmp[1][1] = (*(vector + 1))*(*(vector + 1))*(1 - c) + c;
tmp[1][2] = (*(vector + 1))*(*(vector + 2))*(1 - c) + (*(vector + 0))*s;
tmp[1][3] = 0;
tmp[2][0] = (*(vector + 0))*(*(vector + 2))*(1 - c) + (*(vector + 1))*s;
tmp[2][1] = (*(vector + 1))*(*(vector + 2))*(1 - c) - (*(vector + 0))*s;
tmp[2][2] = (*(vector + 2))*(*(vector + 2))*(1 - c) + c;
tmp[2][3] = 0;
tmp[3][0] = 0;
tmp[3][1] = 0;
tmp[3][2] = 0;
tmp[3][3] = 1;
float tmp_m[4][4];
tmp_m[0][0] = tmp[0][0] * (*(matrix + 0)) + tmp[0][1] * (*(matrix + 4)) + tmp[0][2] * (*(matrix + 8)) + tmp[0][3] * (*(matrix + 12));
tmp_m[0][1] = tmp[0][0] * (*(matrix + 1)) + tmp[0][1] * (*(matrix + 5)) + tmp[0][2] * (*(matrix + 9)) + tmp[0][3] * (*(matrix + 13));
tmp_m[0][2] = tmp[0][0] * (*(matrix + 2)) + tmp[0][1] * (*(matrix + 6)) + tmp[0][2] * (*(matrix + 10)) + tmp[0][3] * (*(matrix + 14));
tmp_m[0][3] = tmp[0][0] * (*(matrix + 3)) + tmp[0][1] * (*(matrix + 7)) + tmp[0][2] * (*(matrix + 11)) + tmp[0][3] * (*(matrix + 15));
tmp_m[1][0] = tmp[1][0] * (*(matrix + 0)) + tmp[1][1] * (*(matrix + 4)) + tmp[1][2] * (*(matrix + 8)) + tmp[1][3] * (*(matrix + 12));
tmp_m[1][1] = tmp[1][0] * (*(matrix + 1)) + tmp[1][1] * (*(matrix + 5)) + tmp[1][2] * (*(matrix + 9)) + tmp[1][3] * (*(matrix + 13));
tmp_m[1][2] = tmp[1][0] * (*(matrix + 2)) + tmp[1][1] * (*(matrix + 6)) + tmp[1][2] * (*(matrix + 10)) + tmp[1][3] * (*(matrix + 14));
tmp_m[1][3] = tmp[0