OpenGL绘制旋转立方体。

首先要用到glm库。在进行PVM变换时可以帮助我们方便地运算。
下载:https://github.com/g-truc/glm/tags

首先是处理顶点数据,由于是一个正方体,有六个面,每个面两个三角形,一共36个点。输入顶点有顶点坐标和顶点的颜色值。这里的坐标是处在模型空间的坐标。

const float vertices[] = {                  //立方体数组
	-0.5f, -0.5f, -0.5f, 1.0f,0.0f,0.0f,    //六个面,每个面两个三角形。
	0.5f, -0.5f, -0.5f,  1.0f,0.0f,0.0f,    //每一行前三个为顶点的坐标,
	0.5f,  0.5f, -0.5f,  1.0f,0.0f,0.0f,    //后三个值为顶点颜色值
	0.5f,  0.5f, -0.5f,  1.0f,0.0f,0.0f,
	-0.5f,  0.5f, -0.5f,  1.0f,0.0f,0.0f,
	-0.5f, -0.5f, -0.5f,  1.0f,0.0f,0.0f,

	-0.5f, -0.5f,  0.5f,  0.0f,1.0f,0.0f,
	0.5f, -0.5f,  0.5f,  0.0f,1.0f,0.0f,
	0.5f,  0.5f,  0.5f,  0.0f,1.0f,0.0f,
	0.5f,  0.5f,  0.5f,  0.0f,1.0f,0.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,1.0f,0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,1.0f,0.0f,

	-0.5f,  0.5f,  0.5f,  0.0f,0.0f,1.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,0.0f,1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,0.0f,1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,0.0f,1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,0.0f,1.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,0.0f,1.0f,

	0.5f,  0.5f,  0.5f,  0.5f,0.0f,0.0f,
	0.5f,  0.5f, -0.5f,  0.5f,0.0f,0.0f,
	0.5f, -0.5f, -0.5f,  0.5f,0.0f,0.0f,
	0.5f, -0.5f, -0.5f,  0.5f,0.0f,0.0f,
	0.5f, -0.5f,  0.5f,  0.5f,0.0f,0.0f,
	0.5f,  0.5f,  0.5f,  0.5f,0.0f,0.0f,

	-0.5f, -0.5f, -0.5f,  0.0f,0.5f,0.0f,
	0.5f, -0.5f, -0.5f,  0.0f,0.5f,0.0f,
	0.5f, -0.5f,  0.5f,  0.0f,0.5f,0.0f,
	0.5f, -0.5f,  0.5f,  0.0f,0.5f,0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,0.5f,0.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,0.5f,0.0f,

	-0.5f,  0.5f, -0.5f,  0.0f,0.0f,0.5f,
	0.5f,  0.5f, -0.5f,  0.0f,0.0f,0.5f,
	0.5f,  0.5f,  0.5f,  0.0f,0.0f,0.5f,
	0.5f,  0.5f,  0.5f,  0.0f,0.0f,0.5f,
	-0.5f,  0.5f,  0.5f,  0.0f,0.0f,0.5f,
	-0.5f,  0.5f, -0.5f,  0.0f,0.0f,0.5f
};

很繁杂,但是一般模型都是导入的,不用自己去一个个顶点的写。

接下来根据坐标转换流程来写:
在这里插入图片描述
PVM变换矩阵就对应于这个过程。

  • model矩阵对应模型变换过程,将局部坐标转换到世界坐标。
  • view矩阵对应

接下来是PVM变换矩阵。实际的变换顺序是“MVP”。Model矩阵用于将模型坐标转化为世界坐标。view矩阵用于从世界坐标转移到观察坐标,要设置观察摄像机的位置,观察方向和头顶方向。projection对应从观察空间到剪裁空间的变换,指定了坐标的范围。
在进入主循环后,得到pvm三个矩阵:

	// Transform坐标变换矩阵
		glm::mat4 model(1);//model矩阵,局部坐标变换至世界坐标
		model = glm::translate(model, glm::vec3(0.0, 0.0, 0.0));
		model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
		model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
		glm::mat4 view(1);//view矩阵,世界坐标变换至观察坐标系
		view = glm::lookAt(camera_position, camera_position + camera_front, camera_up);
		glm::mat4 projection(1);//projection矩阵,投影矩阵
		projection = glm::perspective(glm::radians(fov), (float)screen_width / screen_height, 0.1f, 100.0f);

这里之前要设置view矩阵中摄像机的各参数:

glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);   // 摄像机位置
 
glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);     // 摄像机方向
 
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);         // 摄像机上向量
 

以及projection矩阵中的视角:

float fov=45.0f;

首先计算的是model矩阵

  • 首先要创建一个model矩阵,glm::mat4 model(1)创建一个4*4的单位矩阵。
  • glm::translate()函数用于进行平移变换,将物体平移(0,0,0),也就是不变。
  • glm::rotate()函数用于旋转。第二个参数为旋转角度,第三个参数为旋转轴。这里的glfwGetTime是获取glfw初始化到当前状态所经过的秒数。如果是一个常数的话,就不会旋转了。那是因为每次进入循环之后矩阵在初始状态,都旋转同一个角度,那么肯定就看不到旋转。每次循环旋转不同角度,且这个角度的大小随时间变换,才能看得到旋转效果。
  • glm::scale()函数用于缩放,vec3指定x,y,z三个方向上的缩放比例。
glm::mat4 model(1);//model矩阵,局部坐标变换至世界坐标
model = glm::translate(model, glm::vec3(0.0,0.0,0.0));  
model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 
0.0f));  
model = glm::scale(model, glm::vec3(1.0f,1.0f,1.0f));  

接着是view矩阵

  • 首先还是要创建一个4*4的单位矩阵
  • 通过lookAt函数计算。第一个参数是相机位置,第二个参数是相机所正对的目标的坐标,这里用camera_position+camera_front(相机的方向)进行向量加法后可以得到相机正对的坐标。第三个参数是相机的上向量。
glm::mat4 view(1);//view矩阵,世界坐标变换至观察坐标系
view = glm::lookAt(camera_position, camera_position + camera_front,  
camera_up);

最后是projection矩阵

  • 这是一个投影透视矩阵
  • 第一个参数fov是角度值,定义了视野。对一个真实的观察效果,通常设置为45,如果要看到更多东西需要设置一个更大的值.
  • 第二个参数设置宽高比,也就是屏幕宽度比上屏幕高度。
  • 第三个和第四个参数设置了平截头体(也就是一个四棱台)的近和远平面。通常设置最近距离为0.1,最远距离为100.0。所有在近平面和远平面的顶点且处于平截头体内的顶点都会被渲染。
glm::mat4 projection(1);//projection矩阵,投影矩阵
projection = glm::perspective(glm::radians(fov), (float)screen_width / 
screen_height, 0.1f, 100.0f); 

以上对model,view,projection矩阵进行初始化后,还要将这三个矩阵传入着色器内。

glGetUniformLocation函数可以获得某个着色器中参数的位置,第一个参数为着色器id,第二个参数为该参数的名字

int model_location = glGetUniformLocation(shader.ID, "model");  

glUniformMatrix4fv函数用于向指定位置传入一个4*4矩阵值。

glUniformMatrx4fv(model_location,1,GL_FALSE,glm::value_ptr(model));

接下来看顶点着色器的内容:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 PosColor;
out vec3 positionColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
	positionColor=PosColor;
}

可以看到这里的参数和我们在程序内设置的是对应的。
注意顺序。由于opengl的向量是列向量,与行向量算的方式相反。

猜你喜欢

转载自blog.csdn.net/weixin_42189888/article/details/105100979
今日推荐