上一篇基本复习了一下顶点着色器、片段着色器,能绘制出最基本的带纹理的二维图片。接下来就该介绍三维是怎么一个过程~
本文目录
- 简单变换
- 矩阵基础知识
- 缩放
- 平移
- 旋转
- 矩阵的组合
- 三维系统介绍
- 相机
- 模型加载
- 简单纹理
- 简单光照
- 总结
简单变换
矩阵基础知识
矩阵是什么?
下面这个就是一个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][0] * (*(matrix + 3)) + tmp[1][1] * (*(matrix + 7)) + tmp[1][2] * (*(matrix + 11)) + tmp[1][3] * (*(matrix + 15));
tmp_m[2][0] = tmp[2][0] * (*(matrix + 0)) + tmp[2][1] * (*(matrix + 4)) + tmp[2][2] * (*(matrix + 8)) + tmp[2][3] * (*(matrix + 12));
tmp_m[2][1] = tmp[2][0] * (*(matrix + 1)) + tmp[2][1] * (*(matrix + 5)) + tmp[2][2] * (*(matrix + 9)) + tmp[2][3] * (*(matrix + 13));
tmp_m[2][2] = tmp[2][0] * (*(matrix + 2)) + tmp[2][1] * (*(matrix + 6)) + tmp[2][2] * (*(matrix + 10)) + tmp[2][3] * (*(matrix + 14));
tmp_m[2][3] = tmp[2][0] * (*(matrix + 3)) + tmp[2][1] * (*(matrix + 7)) + tmp[2][2] * (*(matrix + 11)) + tmp[2][3] * (*(matrix + 15));
tmp_m[3][0] = tmp[3][0] * (*(matrix + 0)) + tmp[3][1] * (*(matrix + 4)) + tmp[3][2] * (*(matrix + 8)) + tmp[3][3] * (*(matrix + 12));
tmp_m[3][1] = tmp[3][0] * (*(matrix + 1)) + tmp[3][1] * (*(matrix + 5)) + tmp[3][2] * (*(matrix + 9)) + tmp[3][3] * (*(matrix + 13));
tmp_m[3][2] = tmp[3][0] * (*(matrix + 2)) + tmp[3][1] * (*(matrix + 6)) + tmp[3][2] * (*(matrix + 10)) + tmp[3][3] * (*(matrix + 14));
tmp_m[3][3] = tmp[3][0] * (*(matrix + 3)) + tmp[3][1] * (*(matrix + 7)) + tmp[3][2] * (*(matrix + 11)) + tmp[3][3] * (*(matrix + 15));;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
*(matrix + 4 * i + j) = tmp_m[i][j];
}
//平移
/*
float matrix[4][4];
setone(*matrix);
translate(*matrix, 1.0f, 1.0f, 1.0f);
*/
void translate(float *matrix, float x, float y, float z)
{
float tmp[4][4];
tmp[0][0] = 1;
tmp[0][1] = 0;
tmp[0][2] = 0;
tmp[0][3] = 0;
tmp[1][0] = 0;
tmp[1][1] = 1;
tmp[1][2] = 0;
tmp[1][3] = 0;
tmp[2][0] = 0;
tmp[2][1] = 0;
tmp[2][2] = 1;
tmp[2][3] = 0;
tmp[3][0] = x;
tmp[3][1] = y;
tmp[3][2] = z;
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][0] * (*(matrix + 3)) + tmp[1][1] * (*(matrix + 7)) + tmp[1][2] * (*(matrix + 11)) + tmp[1][3] * (*(matrix + 15));
tmp_m[2][0] = tmp[2][0] * (*(matrix + 0)) + tmp[2][1] * (*(matrix + 4)) + tmp[2][2] * (*(matrix + 8)) + tmp[2][3] * (*(matrix + 12));
tmp_m[2][1] = tmp[2][0] * (*(matrix + 1)) + tmp[2][1] * (*(matrix + 5)) + tmp[2][2] * (*(matrix + 9)) + tmp[2][3] * (*(matrix + 13));
tmp_m[2][2] = tmp[2][0] * (*(matrix + 2)) + tmp[2][1] * (*(matrix + 6)) + tmp[2][2] * (*(matrix + 10)) + tmp[2][3] * (*(matrix + 14));
tmp_m[2][3] = tmp[2][0] * (*(matrix + 3)) + tmp[2][1] * (*(matrix + 7)) + tmp[2][2] * (*(matrix + 11)) + tmp[2][3] * (*(matrix + 15));
tmp_m[3][0] = tmp[3][0] * (*(matrix + 0)) + tmp[3][1] * (*(matrix + 4)) + tmp[3][2] * (*(matrix + 8)) + tmp[3][3] * (*(matrix + 12));
tmp_m[3][1] = tmp[3][0] * (*(matrix + 1)) + tmp[3][1] * (*(matrix + 5)) + tmp[3][2] * (*(matrix + 9)) + tmp[3][3] * (*(matrix + 13));
tmp_m[3][2] = tmp[3][0] * (*(matrix + 2)) + tmp[3][1] * (*(matrix + 6)) + tmp[3][2] * (*(matrix + 10)) + tmp[3][3] * (*(matrix + 14));
tmp_m[3][3] = tmp[3][0] * (*(matrix + 3)) + tmp[3][1] * (*(matrix + 7)) + tmp[3][2] * (*(matrix + 11)) + tmp[3][3] * (*(matrix + 15));;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
*(matrix + 4 * i + j) = tmp_m[i][j];
}
//缩放
/*
float model[4][4];
setone(*model);
scale(*model, -2.0f, -3.15f, 0.0f);
*/
void scale(float *matrix, float x, float y, float z)
{
float tmp[4][4];
tmp[0][0] = x;
tmp[0][1] = 0;
tmp[0][2] = 0;
tmp[0][3] = 0;
tmp[1][0] = 0;
tmp[1][1] = y;
tmp[1][2] = 0;
tmp[1][3] = 0;
tmp[2][0] = 0;
tmp[2][1] = 0;
tmp[2][2] = z;
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][0] * (*(matrix + 3)) + tmp[1][1] * (*(matrix + 7)) + tmp[1][2] * (*(matrix + 11)) + tmp[1][3] * (*(matrix + 15));
tmp_m[2][0] = tmp[2][0] * (*(matrix + 0)) + tmp[2][1] * (*(matrix + 4)) + tmp[2][2] * (*(matrix + 8)) + tmp[2][3] * (*(matrix + 12));
tmp_m[2][1] = tmp[2][0] * (*(matrix + 1)) + tmp[2][1] * (*(matrix + 5)) + tmp[2][2] * (*(matrix + 9)) + tmp[2][3] * (*(matrix + 13));
tmp_m[2][2] = tmp[2][0] * (*(matrix + 2)) + tmp[2][1] * (*(matrix + 6)) + tmp[2][2] * (*(matrix + 10)) + tmp[2][3] * (*(matrix + 14));
tmp_m[2][3] = tmp[2][0] * (*(matrix + 3)) + tmp[2][1] * (*(matrix + 7)) + tmp[2][2] * (*(matrix + 11)) + tmp[2][3] * (*(matrix + 15));
tmp_m[3][0] = tmp[3][0] * (*(matrix + 0)) + tmp[3][1] * (*(matrix + 4)) + tmp[3][2] * (*(matrix + 8)) + tmp[3][3] * (*(matrix + 12));
tmp_m[3][1] = tmp[3][0] * (*(matrix + 1)) + tmp[3][1] * (*(matrix + 5)) + tmp[3][2] * (*(matrix + 9)) + tmp[3][3] * (*(matrix + 13));
tmp_m[3][2] = tmp[3][0] * (*(matrix + 2)) + tmp[3][1] * (*(matrix + 6)) + tmp[3][2] * (*(matrix + 10)) + tmp[3][3] * (*(matrix + 14));
tmp_m[3][3] = tmp[3][0] * (*(matrix + 3)) + tmp[3][1] * (*(matrix + 7)) + tmp[3][2] * (*(matrix + 11)) + tmp[3][3] * (*(matrix + 15));;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
*(matrix + 4 * i + j) = tmp_m[i][j];
}
//摄像头相关矩阵
/*
float view1[4][4];
float eye[3] = { 0.0f,0.0f,8.0f };
float target[3] = { 5.0f,3.0f,0.0f };
float up[3] = { 0.0f,1.0f,0.0f };
lookat(*view1, eye, target, up);
*/
void lookat(float *matrix, float *eye, float *target, float *up)
{
float f[3];
f[0] = target[0] - eye[0];
f[1] = target[1] - eye[1];
f[2] = target[2] - eye[2];
normalize(f);
float s[3];
s[0] = f[1] * up[2] - f[2] * up[1];
s[1] = f[2] * up[0] - f[0] * up[2];
s[2] = f[0] * up[1] - f[1] * up[0];
normalize(s);
float u[3];
u[0] = s[1] * f[2] - s[2] * f[1];
u[1] = s[2] * f[0] - s[0] * f[2];
u[2] = s[0] * f[1] - s[1] * f[0];
float dot[3];
dot[0] = s[0] * eye[0] + s[1] * eye[1] + s[2] * eye[2];
dot[1] = u[0] * eye[0] + u[1] * eye[1] + u[2] * eye[2];
dot[2] = f[0] * eye[0] + f[1] * eye[1] + f[2] * eye[2];
*(matrix + 0) = s[0];
*(matrix + 1) = u[0];
*(matrix + 2) = -f[0];
*(matrix + 3) = 0;
*(matrix + 4) = s[1];
*(matrix + 5) = u[1];
*(matrix + 6) = -f[1];
*(matrix + 7) = 0;
*(matrix + 8) = s[2];
*(matrix + 9) = u[2];
*(matrix + 10) = -f[2];
*(matrix + 11) = 0;
*(matrix + 12) = -dot[0];
*(matrix + 13) = -dot[1];
*(matrix + 14) = dot[2];
*(matrix + 15) = 1;
}
/*矩阵相乘*/
void mal4_4(float *matrix, float *matrix1, float *matrix2)
{
float temp[16];
temp[0] = (*(matrix1 + 0)) * (*(matrix2 + 0)) + (*(matrix1 + 1)) * (*(matrix2 + 4)) + (*(matrix1 + 2)) * (*(matrix2 + 8)) + (*(matrix1 + 3)) * (*(matrix2 + 12));
temp[1] = (*(matrix1 + 0)) * (*(matrix2 + 1)) + (*(matrix1 + 1)) * (*(matrix2 + 5)) + (*(matrix1 + 2)) * (*(matrix2 + 9)) + (*(matrix1 + 3)) * (*(matrix2 + 13));
temp[2] = (*(matrix1 + 0)) * (*(matrix2 + 2)) + (*(matrix1 + 1)) * (*(matrix2 + 6)) + (*(matrix1 + 2)) * (*(matrix2 + 10)) + (*(matrix1 + 3)) * (*(matrix2 + 14));
temp[3] = (*(matrix1 + 0)) * (*(matrix2 + 3)) + (*(matrix1 + 1)) * (*(matrix2 + 7)) + (*(matrix1 + 2)) * (*(matrix2 + 11)) + (*(matrix1 + 3)) * (*(matrix2 + 15));
temp[4] = (*(matrix1 + 4)) * (*(matrix2 + 0)) + (*(matrix1 + 5)) * (*(matrix2 + 4)) + (*(matrix1 + 6)) * (*(matrix2 + 8)) + (*(matrix1 + 7)) * (*(matrix2 + 12));
temp[5] = (*(matrix1 + 4)) * (*(matrix2 + 1)) + (*(matrix1 + 5)) * (*(matrix2 + 5)) + (*(matrix1 + 6)) * (*(matrix2 + 9)) + (*(matrix1 + 7)) * (*(matrix2 + 13));
temp[6] = (*(matrix1 + 4)) * (*(matrix2 + 2)) + (*(matrix1 + 5)) * (*(matrix2 + 6)) + (*(matrix1 + 6)) * (*(matrix2 + 10)) + (*(matrix1 + 7)) * (*(matrix2 + 14));
temp[7] = (*(matrix1 + 4)) * (*(matrix2 + 3)) + (*(matrix1 + 5)) * (*(matrix2 + 7)) + (*(matrix1 + 6)) * (*(matrix2 + 11)) + (*(matrix1 + 7)) * (*(matrix2 + 15));
temp[8] = (*(matrix1 + 8)) * (*(matrix2 + 0)) + (*(matrix1 + 9)) * (*(matrix2 + 4)) + (*(matrix1 + 10)) * (*(matrix2 + 8)) + (*(matrix1 + 11)) * (*(matrix2 + 12));
temp[9] = (*(matrix1 + 8)) * (*(matrix2 + 1)) + (*(matrix1 + 9)) * (*(matrix2 + 5)) + (*(matrix1 + 10)) * (*(matrix2 + 9)) + (*(matrix1 + 11)) * (*(matrix2 + 13));
temp[10] = (*(matrix1 + 8)) * (*(matrix2 + 2)) + (*(matrix1 + 9)) * (*(matrix2 + 6)) + (*(matrix1 + 10)) * (*(matrix2 + 10)) + (*(matrix1 + 11)) * (*(matrix2 + 14));
temp[11] = (*(matrix1 + 8)) * (*(matrix2 + 3)) + (*(matrix1 + 9)) * (*(matrix2 + 7)) + (*(matrix1 + 10)) * (*(matrix2 + 11)) + (*(matrix1 + 11)) * (*(matrix2 + 15));
temp[12] = (*(matrix1 + 12)) * (*(matrix2 + 0)) + (*(matrix1 + 13)) * (*(matrix2 + 4)) + (*(matrix1 + 14)) * (*(matrix2 + 8)) + (*(matrix1 + 15)) * (*(matrix2 + 12));
temp[13] = (*(matrix1 + 12)) * (*(matrix2 + 1)) + (*(matrix1 + 13)) * (*(matrix2 + 5)) + (*(matrix1 + 14)) * (*(matrix2 + 9)) + (*(matrix1 + 15)) * (*(matrix2 + 13));
temp[14] = (*(matrix1 + 12)) * (*(matrix2 + 2)) + (*(matrix1 + 13)) * (*(matrix2 + 6)) + (*(matrix1 + 14)) * (*(matrix2 + 10)) + (*(matrix1 + 15)) * (*(matrix2 + 14));
temp[15] = (*(matrix1 + 12)) * (*(matrix2 + 3)) + (*(matrix1 + 13)) * (*(matrix2 + 7)) + (*(matrix1 + 14)) * (*(matrix2 + 11)) + (*(matrix1 + 15)) * (*(matrix2 + 15));
*(matrix + 0) = temp[0];
*(matrix + 1) = temp[1];
*(matrix + 2) = temp[2];
*(matrix + 3) = temp[3];
*(matrix + 4) = temp[4];
*(matrix + 5) = temp[5];
*(matrix + 6) = temp[6];
*(matrix + 7) = temp[7];
*(matrix + 8) = temp[8];
*(matrix + 9) = temp[9];
*(matrix + 10) = temp[10];
*(matrix + 11) = temp[11];
*(matrix + 12) = temp[12];
*(matrix + 13) = temp[13];
*(matrix + 14) = temp[14];
*(matrix + 15) = temp[15];
}
模型加载
我用的是obj模型,在3D-max里可以设置输出的数据结构。 常见可以输出的数值有
顶点数据(Vertex data): v 几何体顶点 (Geometric vertices) vt 贴图坐标点 (Texture vertices) vn 顶点法线 (Vertex normals) vp 参数空格顶点 (Parameter space vertices) 元素(Elements): p 点 (Point) l 线 (Line) f 面 (Face)
我只使用了v、vt、vn、f。我用的是三角形,也可以用四边形画。 保存后一般用txt打开一般会长这个样子。
v -0.58 0.84 0 v 2.68 1.17 0 v 2.84 -2.03 0 f 1 2 3
f这个是顶点的索引值。 因为obj这个保存还是偏大的,而且读取也不方便,我自己做了一个数据转换,按我想要的格式进行数据保存,保存为二进制格式。 代码已经找不到了。。。只能讲讲逻辑,以后有必要再补吧。
简单纹理
// texture的输入
glUniform1i(Prgm_3D_texture_UNFM_Amb, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, PNG_id[PNG_car]);
// 片段着色器
#version 330 core
uniform sampler2D picture;
in vec2 TexCoords;
void main()
{
gl_FragColor = texture(picture, TexCoords) ;
}
简单光照
光的颜色可以在片段着色器里进行修改
嗯其实很多特效我也不会写,就看一个复杂的然后删删改改
比如一个结合了环境光,点光源等的片段着色器是这样的
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 4
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;
// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
// properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// == =====================================================
// Our lighting is set up in 3 phases: directional, point lights and an optional flashlight
// For each phase, a calculate function is defined that calculates the corresponding color
// per lamp. In the main() function we take all the calculated colors and sum them up for
// this fragment's final color.
// == =====================================================
// phase 1: directional lighting
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// phase 2: point lights
for(int i = 0; i < NR_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
// phase 3: spot light
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
FragColor = vec4(result, 1.0);
}
// calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
return (ambient + diffuse + specular);
}
// calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
// calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// spotlight intensity
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (ambient + diffuse + specular);
}
整个项目的工程代码看这 https://learnopengl.com/code_viewer_gh.php?code=src/2.lighting/6.multiple_lights/multiple_lights.cpp
总结
最后这里放一个酷炫的模型作为本文的 总结吧。
代码在这:https://learnopengl.com/code_viewer_gh.php?code=src/3.model_loading/1.model_loading/model_loading.cpp 效果在这: