文章目录
实验内容实验步骤1、场景设计和显示2、添加纹理3、添加光照、材质、阴影效果4、用户交互实现视角切换完成对场景的任意角度浏览5、通过交互控制物体*6、补充说明实验效果场景效果其他物体效果使用说明实验内容
在屏幕上显示一个包含多个虚拟物体的虚拟场景,并响应一定的用户交互操作。
场景设计和显示
学生可以通过层级建模( 实验补充1和2)的方式建立多个虚拟物体,由多个虚拟物体组成一个虚拟场景,要求在程序中显示该虚拟场景,场景可以是室内或者室外场景;场景应包含地面。层级建模的最深层次需要达到至少四层。添加纹理
参考实验4.1,为场景中至少两个主要物体添加纹理贴图 。添加光照、材质、阴影效果
参考实验3.2,实验3.3和实验3.4,实现光照效果、材质、阴影等。用户交互实现视角切换完成对场景的任意角度浏览
参考实验3.1,完成相机变换。通过交互控制物体
参考实验2.3,实现物体的变换,允许用户通过键盘或者鼠标实现场景中至少两个物体的控制(移动,旋转,缩放等等)。
实验步骤
1、场景设计和显示
①、本次实验我将绘制一个平台作为地面,将所有虚拟物体放在上面。
此处推荐一个图形学神器软件:MagicaVoxel。
在MagicaVoxel内可以自由绘制像素模型,以obj格式保存后即可读取到作业中。
②、层级建模
(1)、人物模型幽灵结构框图:
(2)、通过Magicavoxel绘制出人物的各个身体部件。参考实验补充2,先将各部分初始化(以躯干为例):
(3)、随后以obj的方式读入:
(4)、随后,以躯干(Torso)开始构建层级,后续调整人物位置只需要调整躯干即可(为方便位置调整,我定义了全局变量x_step_size和_y_step_size来控制模型在平面的位置):
2、添加纹理
①、设置TriMesh.cpp,
(1)、纹理坐标位置:
(2)、读取obj时,读取到纹理坐标:
(3)、随后来存储点对应的纹理坐标:
②、着色器的纹理设置
(1)顶点着色器中添加传给片元着色器的纹理变量texCoord,随后传给片元着色器:
(2)、片元着色器中定义接收纹理数据的fColor,接收顶点着色器传来的纹理数据:
③、随后MeshPainter.cpp中的load_texture_STBImage函数即可正常读取纹理图片,并将其传递给着色器,同时在bindObjectAndData函数中,绑定纹理数据并将纹理坐标传给着色器:
④、使用bindObjectAndData初始化各种对象后,即可添加obj及其纹理图片进行绘制:
3、添加光照、材质、阴影效果
①、首先设置光源的位置,同时设置光源的参数:
②、设置Torso的材质,让Torso可以反光:
③、在addMesh函数中添加阴影绘制代码:
④、addMesh中的bindLightAndMaterial函数用来传递光照、材质等数据:
⑤、随后在片元着色器中添加四个归一的法向量,同时添加光的反色系数:
之后绘制的物体即可正常有反光性质,同时在y=0的平面生成阴影。
4、用户交互实现视角切换完成对场景的任意角度浏览
①、首先在Camera.h中初始化相机的参数(观察位置):
②、随后添加键盘、鼠标的交互
(1)键盘中使用如下按键交互:
u/U: 增加/减小相机的rotateAngle,即向右/左移动相机;
i/I: 增加/减小相机的upAngle,即向上/下移动相机;
o/O: 增加/减小相机的radius,即拉远/近相机;
space: 相机回到初始位置。
(2)、鼠标中使用如下操作来交互
鼠标滚轮向前/后滑动: 减小/增大radius,即可拉进/远相机位置;
以界面中心为坐标原点建立二维坐标,鼠标在界面移动,相机可以往坐标的地方移动。
5、通过交互控制物体
①、幽灵转身/行走
(1)、转身。
首先参考实验补充2,通过按键a / d来使torso的theta减小/增大,从而达到让其向左/右转身:
(2)、行走。
A、将其行走动作拆分:左右小腿分别往前时,以及再插入站立时,四种状态;通过设置躯干角度来实现,通过walk函数不断循环即可(下图角度以第一步行走为例):
B、绘制幽灵时,之前提到的幽灵初始位置由躯干坐标(x_step_size, 0, y_step_size)来控制。以向左走为例:按方向键←时,躯干的theta减少90°,即幽灵向左转身,同时躯干的位置向左移动0.1个单位,可通过按压来实现一直行走。所以加入键盘交互如下:
②、风车的旋转
(1)、绘制风车翼时,使用变量r来控制角度:
(2)、随后写个渲染r自动增大的函数autoRotate,并在display函数中调用,即可实现风车的自动旋转:
(3)、在键盘交互中,也可通过按 f 键来加快风车的旋转速度(可按压):
③、妹子NPC的放大/缩小
(1)、绘制妹子时,使用变量s来控制其setScale:
(2)、随后在键盘交互中,通过按键l / L来实现妹子NPC的放大/缩小:
*在main函数中加入抗锯齿效果,可使物体运动更流畅:
glfwWindowHint(GLFW_SAMPLES, 8);
*6、补充说明
考虑到虚拟场景的多样的以及基于现实的可能性,我使用addMesh绘制房子、风车等物体,使之在地面上存在阴影,但我也绘制了部分“没有阴影”的物体,如:地面(需要阴影落在地面上)、池塘(池塘镶嵌在地面内,自身不存在影子)、幽灵(幽灵没有影子)。
所以我在MeshPainter.h和MeshPainter.cpp中,添加了drawMesh2,取消了其阴影绘制部分,在绘制这些物体时,就使用此函数来传递变换矩阵,即可去除这些物体的影子。
实验效果
场景效果
其他物体效果
使用说明
项目地址
1、鼠标交互
①、鼠标滚轮向前/后滑动可以拉进/远相机位置;
②、以界面中心为坐标原点建立二维坐标,鼠标在界面移动,相机可以往坐标的地方移动。
2、键盘交互
①、幽灵:
方向键↑: 控制幽灵转身往前走;
方向键↓: 控制幽灵转身往后走;
方向键←: 控制幽灵转身往左走;
方向键→: 控制幽灵转身往右走。
a: 控制幽灵往左边旋转
d: 控制幽灵往右边旋转
②、风车(已自动旋转)
f: 手动加速风车旋转。
③、妹子:
l/L: 放大/缩小妹子。
④、相机:
SPACE: 相机回到初始位置;
u/U: 相机往右/左旋转;
i/I: 相机往上/下旋转;
o/O: 相机视角拉远/拉近。
⑤、页面
h: 弹出操作提示;
ESC: 退出。