CG-Assignment1
计算机图形学作业1
本文为计算机图形学作业2报告, 为本人计算机图形学课程作业, 仅供参考, 未经允许不得转载, 抄袭.
1.引言
本次项目完成作业1,实现了对obj文件的加载, 并对模型进行键盘和鼠标控制
具体实现如下:
- 实现obj文件的加载
- 对模型加键盘控制,通过键盘可以实现模型的缩放、平移和旋转。
例如,按压右/左方向键,模型可以向右/左移动。具体按键和其对应的功能自行设定,但需要在报告中详细给出文字说明。 - 对相机加鼠标控制,主要包含以下两个功能:
a. 模型本身保持固定,拖动鼠标左键实现视角 (lookat matrix)的改变
b. 模型本身保持固定,拖动鼠标右键实现视点(viewpoint position)的移动
2. 主体介绍
2.1 程序简介
编程环境
MacOS,C++11,IDE: CLion,cmake,使用OpenGL,Glad,GLFW3.3.8,glm0.9.9.1以及Assimp
文件结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Computer_Graphics_Assign1
│
├── model_loading.cpp
├── 1.model_loading.fs
├── 1.model_loading.vs
├── CMakeLists.txt
├──
├── OBJ_Files
│ ├── airboat.obj
│ └── bunny.obj
│
├── includes
│ ├── camera.h
│ ├── model.h
│ ├── shader.h
│ └── mesh.h
└── ...Glad & Glm & cmake-build-debug
2.2 算法
在这一部分需要描述你的项目实现过程中用了哪些算法,需要你从算法背后的原理入手结合自己的项目进行描述,切忌段落式的粘贴代码,如果是自己写的算法,进行适当的算法复杂度分析。
示例:a) Lambert 漫反射光照模型 b) 正投影相机 c) Phong光照模型 d) 一些图形的绘制举例 e) 碰撞测试特例算法
注:一定要结合自己的项目去写这一部分,落到实处,切忌直接从网上直接粘贴理论知识。
2.2.1 OBJ文件的加载
首先是对于OBJ文件的加载,我使用了一个非常流行的模型导入库——Assimp
Assimp能够导入很多种不同的模型文件格式,它会将所有的模型数据加载至Assimp的通用数据结构中。当Assimp加载完模型之后,就能够从Assimp的数据结构中提取所需的所有数据。
- 所有的场景/模型数据都包含在Scene对象
- 一个Mesh对象本身包含了渲染所需要的所有相关数据,像是顶点位置、法向量、纹理坐标、面(Face)和物体的材质。
- 最终仍要将这些数据转换为OpenGL能够理解的格式,才能渲染这个物体
2.2.2 键盘鼠标控制操作
详细思想和代码实现见Camera和Model_loading处
2.3 实现细节
在这一部分,将自己的项目拆解成各个部分进行说明。切忌段落式的粘贴代码。
第二章应占整体篇幅的40%。
2.3.1 Mesh网格
定义一个顶点结构体
1 | struct Vertex { |
定义网格类
构造函数导入导入数据,调用setupMesh()
方法,在setupMesh()
函数中初始化缓冲,并最终使用Draw()
函数来绘制网格
构造函数
1 | Mesh(vector<Vertex> vertices, vector<unsigned int> indices) |
其中包含setupMesh()
1 | void setupMesh() |
以及提供Draw()
,绘制每个mesh
1 | void Draw(Shader &shader) |
2.3.2 Model模型
定义Model类
1 | class Model |
构造函数
其中包含了一个Mesh对象的vector,构造函数包含loadModel()
函数和draw()
函数
draw()
函数遍历了所有网格,并调用它们各自的Draw
函数
1 | void Draw(Shader shader) |
loadModel()
函数,需要传入一个文件路径path,之后使用Assimp来加载模型至Assimp的一个叫做scene的数据结构中
1 |
|
之后调用processMesh()
函数,这样就可以将从obj模型文件中加载出的数据处理到我设置的Mesh类中
1 | Mesh processMesh(aiMesh *mesh, const aiScene *scene) { |
2.3.3 shader.h
与上课时给出的shader.h代码相同
使用C++文件流读取着色器内容,储存到几个string
对象里
以下实现了对着色器的编译和链接
1 | unsigned int vertex, fragment; |
定义了
1 | void use() const { glUseProgram(ID); } |
2.3.4 camera.h
提供ProcessKeyboard
, ProcessMouseMovement
, ProcessMouseScroll
方法,用于实现鼠标键盘控制
Camera 类 定义了位置,接收变化的变量,欧拉角,选项和构造函数,此外还有键盘鼠标操作函数和相机更新函数
1 | class Camera |
ProcessKeyboard处理从任何类似键盘的输入系统接收的输入
1 | void ProcessKeyboard(Camera_Movement direction, float deltaTime) |
ProcessMouseMovement处理从鼠标输入系统接收的输入。期望x和y方向上的偏移值。
1 | void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true) |
ProcessMouseScroll
处理从鼠标滚轮事件接收的输入。只需要在垂直轮轴上输入
1 | void ProcessMouseScroll(float yoffset) |
updateCameraVectors
1 | void updateCameraVectors() |
2.3.5 model_loading(Main方法)
主方法
加载Shader,Model,Camera
Camera camera(glm::vec3(0.0f, 0.0f, 10.0f));
Shader ourShader("../1.model_loading.vs", "../1.model_loading.fs");
Model ourModel("../OBJ_Files/airboat.obj");
鼠标键盘操作
processInput
(定义了键盘按键对应上下左右前后操作) 见processInput(GLFWwindow *window)
- W上/ S下/ A左/ D右/ Q前/ E后
1 | void processInput(GLFWwindow *window) |
mouse_button_callback
, mouse_callback
, scroll_callback
实现了鼠标的操作
mouse_button_callback
是检测鼠标点击左键右键时候对相机的更新操作mouse_callback
是检测到鼠标移动时对相机的更新操作==这里定义了两个bool值来判断,只有在按压左键/右键时才对鼠标的移动进行处理==
1 | bool leftMouseButtonDown = false; |
鼠标滚轮
1
2
3
4void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(static_cast<float>(yoffset));
}
加载窗口,使用之前配置的Model, Mesh, Camera, Shader
1 |
|
2.3.6 着色器配置文件
由于obj文件没有纹理和材质的信息,因此我加入了光照使得可以看清模型的立体结构
无光照效果如下
加入光照后效果如下
1.model_loading.vs
1 |
|
1.model_loading.fs
1 |
|
3. 结果与讨论
3.1 结果
初始效果
##### 向前 ##### 向后 ##### 向上 ##### 旋转其他具体操作见视频
3.2 讨论
在这一部分,你需要对你在开发过程中遇到的一些困难进行描述和你是如何攻克的,在方法上和结果上展开叙述。
第三章占整体篇幅的30%。
- 模型加载和显示问题:最初尝试自己解析和加载OBJ文件时,我遇到了各种问题,包括正确读取文件、解析顶点、法线和纹理坐标数据等。这些问题耗费了很多时间。然而,通过使用Assimp库,加载模型变得更加容易和高效。
- 相机控制和光照调试:实现键盘和鼠标控制相机位置和方向时,需要深入理解OpenGL的视图和投影矩阵,以及如何处理用户输入。同时,由于最开始没有材质纹理和光照,显示效果很糟糕,我尝试自己学习添加光照,添加光照效果也需要仔细调整材质、光照强度和颜色等参数,以获得满意的渲染结果。
- 着色器编写:编写顶点和片段着色器来实现光照模型是一个有挑战性的任务。理解光照模型的原理,以及如何在着色器中计算环境光、漫反射和镜面反射等部分也很有挑战
4. 收获和建议
课程收获,项目开发收获,课程建议等各个方面展开来叙述。内容上要有意义,量上要占整篇报告的10%左右。
- 更深入的理解OpenGL:通过项目,我加深了对OpenGL的理解,包括顶点和片段着色器、VBO、VAO等概念。我学会了如何加载和渲染3D模型,以及如何处理用户输入来控制相机位置和方向。
- 熟悉了Assimp库:使用Assimp库来加载模型是一个非常有用的技能,它使加载不同格式的3D模型变得更加容易。我学到了如何使用Assimp导入模型数据,以及如何在OpenGL中使用这些数据。
文章作者: Alan Zeng
最后更新:
原始链接: https://alanzeng.com/blogs/17893/
版权说明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 4.0许可协议 。获得许可后,要求转载时注明文章出处和网站链接,谢谢!