使用OpenGL实现场景构建

效果呈现

操作方法说明

1、 移动鼠标可以控制相机的视角

2、 滚动鼠标滚轮从而拉近/远视角

3、 按键盘的空格键重置相机位置

4、 按键盘的w、s,控制人物向前后移动

5、 按键盘的a、d控制人物向左、右转

6、 按键盘的ESC键退出游戏

效果展示

使用OpenGL实现场景构建_第1张图片

使用OpenGL实现场景构建_第2张图片

具体内容

场景设计和显示

通过层级建模的方式建立多个虚拟物体,由多个虚拟物体组成一个虚拟场景,

添加纹理

为场景中主要物体添加纹理贴图 。

添加光照、材质、阴影效果

实现光照效果、材质、阴影等。

用户交互实现视角切换完成对场景的任意角度浏览

完成相机变换。

通过交互控制物体

实现物体的变换,通过键盘和鼠标实现场景中物体的控制(移动,旋转,缩放等等)。

实现步骤

1. 读取并加载模型

首先obj文件中分别含有顶点信息、纹理信息、颜色信息、法线信息,我们需要将所有的信息进行读取,并且进行保存。

顶点信息是以v开头的字符串、纹理信息是以vt开头的字符串、法线信息是以vn开头的字符串,因此我们只需要识别对应的字符,即可保存相关的信息。

因为obj文件中并没有颜色信息,因此我们可以使用法线信息来代替颜色信息(tips:需要将法线信息进行取正操作)

具体的实现如下:

使用OpenGL实现场景构建_第3张图片

将obj文件中的信息保存完成之后,我们需要进行存储操作,即将对应的信息进行重组,从而获得我们需要的信息,具体过程如下:

使用OpenGL实现场景构建_第4张图片

我们读取一个汽车模型来进行测试,结果如下图:

使用OpenGL实现场景构建_第5张图片

2. 实现光照效果

首先我们定义一个light类,然后添加和光照相关的一些参数到类当中,如下图:

使用OpenGL实现场景构建_第6张图片

然后我们需要添加一个全局光照,并且设置光照点的位置、环境光、镜面反射、衰减系数,如下:

使用OpenGL实现场景构建_第7张图片

最后对于每一个模型,我们都给它添加一些光照参数,使之看起来更加真实,如下图:

使用OpenGL实现场景构建_第8张图片

3. 实现阴影效果

首先我们需要先设置阴影投影矩阵,如下:

使用OpenGL实现场景构建_第9张图片

然后进行对每一个模型,我们都进行独立的阴影绘制,如下:

使用OpenGL实现场景构建_第10张图片

最后查看阴影效果,如下图:

使用OpenGL实现场景构建_第11张图片

4. 相机视角的移动

对于相机视角的移动,我们通过改变俯仰角、偏航角、滚轮角来进行实现

使用OpenGL实现场景构建_第12张图片

经过数学推导之后,可以得到:

即,我们通过改变俯仰角、偏航角可以变更相机的视角方向。

这里我们通过使用鼠标位置移动,来改变相机视角,在main函数当中绑定mousepos函数:

使用OpenGL实现场景构建_第13张图片

使用OpenGL实现场景构建_第14张图片

然后我们控制俯仰角不能小于-89,也不能小于89,从而保证用户只能看到天空或脚下但是不能更进一步超越过去,实现如下:

使用OpenGL实现场景构建_第15张图片

然后我们通过滚动鼠标滚轮来控制相机的视野大小。在主函数当中当顶sroll函数:

使用OpenGL实现场景构建_第16张图片

使用OpenGL实现场景构建_第17张图片

然后我们在主函数中使用glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED),从而将鼠标的光标进行隐藏,将鼠标定在我们的场景中,从而提高用户体验。

这样我们就可以通过滚动鼠标滚轮、移动鼠标,从而达到控制相机视角的效果。

5. 层次建模

首先,先确定人物各个模块关系,如下图:

使用OpenGL实现场景构建_第18张图片

即:body->head->hat

Body->left_upper_arm->left_lower_arm

Body->right_upper_arm->right_lower_arm

Body->left_upper_leg->left_lower_leg

Body->right->upper_leg->right->lower_leg

然后我们首先为每一个部位单独写一个绘制函数,方便后续在人物总体绘制函数当中调用绘制

以body为例:

使用OpenGL实现场景构建_第19张图片

使用OpenGL实现场景构建_第20张图片

使用OpenGL实现场景构建_第21张图片

使用OpenGL实现场景构建_第22张图片

接着,创建一个用于保存变换矩阵的类,用于保存各个层级的变换矩阵,如下图:

使用OpenGL实现场景构建_第23张图片

然后写一个人物绘制主函数,在主函数当中调用上述的函数,进行依次绘制,如下图:

使用OpenGL实现场景构建_第24张图片

为了使人物的移动不那么硬核,我们为每一部位添加一个关节角,然后在键盘控制人物进行移动的时候改变关节角,从而实现手、脚在人物移动的过程中进行规律的摆动,如下图:

使用OpenGL实现场景构建_第25张图片

6. 人物移动

首先实现人物在移动的过程中,手和脚的摆动。

设置一个记录帧数的变量,然后在使用键盘控制人物移动的时候,改变该变量,如下图:

然后编写一个函数,用于改变人物的关节角,如下图:

使用OpenGL实现场景构建_第26张图片

接着我们写一个改变人物位置的函数,方便键盘函数的调用,如下图:

使用OpenGL实现场景构建_第27张图片

然后在键盘回应函数当中,写入当按下w、s键时,分别改变人物的位置参数,如下图:

使用OpenGL实现场景构建_第28张图片

为了实现按下键盘w、s的时候,人物朝前、后移动,需要根据人物的朝向(关节角)来改变人物的位置参数,数学推导如下:

函数如下图:

使用OpenGL实现场景构建_第29张图片

然后在键盘的a、d被按下时,改变人物的朝向(关节角),如下图:

使用OpenGL实现场景构建_第30张图片

使用OpenGL实现场景构建_第31张图片

这样就实现了通过键盘的a、d改变人物朝向,通过键盘的w、s控制人物向前(后)移动。

效果图如下:

使用OpenGL实现场景构建_第32张图片

7. 加入天空盒

为了让场景更加写实,添加一个天空盒。

首先需要获取天空盒资源,即一个立方体贴图,如下:

使用OpenGL实现场景构建_第33张图片

然后分别绘制六个正方形,并且将立方体贴图分别贴到对应的正方形中,六个正方形需要构成一个完整的正方体,数据如下:

使用OpenGL实现场景构建_第34张图片

然后为back、front、top、buttom、left、right面分别写一个绑定纹理贴图的函数,如下图:

使用OpenGL实现场景构建_第35张图片

然后在主函数中进行绘制,如下:

使用OpenGL实现场景构建_第36张图片

天空盒的效果如下:

使用OpenGL实现场景构建_第37张图片

你可能感兴趣的:(c++)