上一篇基本复习了一下顶点着色器、片段着色器,能绘制出最基本的带纹理的二维图片。接下来就该介绍三维是怎么一个过程~

本文目录

  • 简单变换
  • 矩阵基础知识
  • 缩放
  • 平移
  • 旋转
  • 矩阵的组合
  • 三维系统介绍
  • 相机
  • 模型加载
  • 简单纹理
  • 简单光照
  • 总结

简单变换

矩阵基础知识

矩阵是什么?

下面这个就是一个2X3矩阵,图片其实可以认为是这么一个矩阵,里面的元素是rgb像素

android opengl 旋转动画 opengl三维旋转代码_缩放

矩阵的运算矩阵拥有和数值一样的加减乘除运算。

加(减)法(以下分别是跟标量和跟矩阵的加法):

android opengl 旋转动画 opengl三维旋转代码_opengl_02

android opengl 旋转动画 opengl三维旋转代码_缩放_03

矩阵乘法:

和数值的乘法

android opengl 旋转动画 opengl三维旋转代码_opengl_04

矩阵相乘

android opengl 旋转动画 opengl三维旋转代码_shader_05

缩放

假设向量v=(3,2) ,我们可以把向量沿着x轴缩放0.5,沿着y轴缩放2倍,得到的s如下图所示

android opengl 旋转动画 opengl三维旋转代码_计算机视觉_06

可以定义空间的缩放举证如下

android opengl 旋转动画 opengl三维旋转代码_缩放_07

平移

android opengl 旋转动画 opengl三维旋转代码_缩放_08

旋转

9

android opengl 旋转动画 opengl三维旋转代码_opengl_09

任意角度旋转(Rx,Ry,Rz)包含任意旋转轴

android opengl 旋转动画 opengl三维旋转代码_计算机视觉_10

矩阵的组合

这个就是注意旋转平移的先后顺序!!!! 矩阵计算的代码可以结合后面介绍的相机计算代码一起放在同一个util文件中

三维系统介绍

我们在观察实际的物体的时候,都是有一个透视效果,也即是近大远小。比如下图所示,实际的轨道其实是2个平行线,但是视觉效果在远方会相交。

android opengl 旋转动画 opengl三维旋转代码_opengl_11

相机

首先我们先看一些材料里常见的计算公式。

android opengl 旋转动画 opengl三维旋转代码_shader_12

如何去理解这个公式

Mprojection 是投影矩阵:

实际我们能观察到的内容,是有一个限制区域的,如下图所示

android opengl 旋转动画 opengl三维旋转代码_android opengl 旋转动画_13

能观察到的物体应该是在near plane和far plane所夹的梯形区域内。比如上图中的蓝色小矩形体就不能被摄像头观察到。

通过FOV角度、视角宽高比、近远距离可以定量描述这个区域

通常用到的函数如下,第一个参数是FOV角度,第二个参数是宽高比,第三个参数是近距离,第四个参数是远距离。

glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);

Mview 是观察矩阵:

简单来说就是这个摄像机的位置姿态描述。如下图所示

android opengl 旋转动画 opengl三维旋转代码_opengl_14

数学的描述就是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 效果在这:

android opengl 旋转动画 opengl三维旋转代码_缩放_15