最终演示
Assimp模型渲染
- 模型导入库Assimp:导入很多种不同的模型文件格式,加载至Assimp的通用数据结构(树形)中,不论导入的是什么种类的文件格式,用同一种方式访问我们需要的数据。
-
Assimp库配置:
- premake5.lua:cmake构建出sln,对于assimp project构建动态库(lib和dl),include头文件
- 运行premake5.exe,build两个project,
- assimp-vc143-mtd.lib:assimp-master\build\lib
- assimp-vc143-mtd.dll:assimp-master\build\bin\Debug
- 运行❌:找不到config.h :在assimp-master\build\include\assimp,config.h放置到assimp-master\include\assimp 目录下
- 这回加入include运行项目成功
- 配置参考, 配置参考
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
-
数据结构:
- 将整个模型加载进一个场景(Scene)对象,场景存储所有模型数据数组(真正的Mesh/Material对象),
- 接着场景载入为一系列的节点(Node),每个节点包含了场景对象中所储存数据的索引
- Scene对象(根节点的引用,)
- Root node(根节点)包含子节点和场景中网格数组的索引
- Mesh对象(包含了渲染所需要的所有相关数据,像是顶点位置、法向量、纹理坐标、面(Face)和物体的材质)Face代表的是物体的渲染图元(Primitive)(三角形、方形、点)
- Material对象,它包含了一些函数能让我们获取物体的材质属性,比如说颜色和纹理贴图(比如漫反射和镜面光贴图),结果是一系列的网格数据,包含在一个
Model
对象中
-
实现过程:
- 模型加载到Scene对象中,递归搜索每个节点的子节点,获取对应的Mesh对象
- 不需要将整个模型渲染为一个整体,只需要渲染组成模型的每个独立的网格就可以了
- model类(模型对象)(包含全部网格),
- mesh类(一个网格对象)(单个的可绘制实体)(负责网格绘制渲染)
-
具体代码:
-
struct Vertex,struct Texture
-
mesh的思路,依然是传入数据,初始化,渲染绘制的过程,
- setupMesh()
- C++结构体有一个很棒的特性,它们的内存布局是连续的(Sequential),和原来的数组没什么区别,我们能够直接传入一大列的Vertex结构体的指针作为缓冲的数据
- 不同的是,这回在VBO,VEO中传入的是struct,原来传入的数组,包含全部顶点的顶点/索引数据,一个结构体指包含一个顶点/索引数据,那么需要传入vector<struct>
- 并设置layout(
sizeof(),
计算它的字节大小,预处理指令offsetof(
结构体,
结构体中变量的名字)
变量距结构体头部的字节偏移量(Byte Offset))
- Draw():
绑定纹理:
一开始并不知道这个网格有多少纹理、纹理是什么类型的。- 设定一个命名标准:漫反射纹理被命名为
texture_diffuseN
,每个镜面光纹理应该被命名为texture_specularN(N
的范围是1到纹理采样器最大允许的数字)
-
model的思路:基本上就是遍历了所有网格,并调用它们各自的Draw函数
- vector<Mesh>meshes。
- Model()传入path
- Draw()通过for循环所有的meshes,进行渲染
- loadModel()Assimp::Importer加载模型到aiScene*场景中,检查……,处理节点processNode()
- processNode()递归处理树的每个节点aiNode *,
- 遍历检查当前节点的mNumMeshes网格数量,从aiScene*的mMeshes找到对应的网格数据
- 将这个数据传入processMesh(),返回iMesh并添加到meshes数组中,
- 遍历检查当前节点的mNumChildren子节点数量,递归processNode(),终止条件:所有的节点都被处理完毕,
- processMesh()
aiMesh
对象转化自己的Mesh类(调用构造),- 循环mNumVertices,mNumFaces(mNumIndices),的个数,用库的函数mesh->mVertices等添加到数组,
- 传给mesh的构造函数(vertices, indices, textures),return 创建的mesh类对象
- loadMaterialTextures()检查给定类型的所有材质纹理,如果尚未加载,则加载这些纹理。 所需的信息将作为纹理结构返回。
-
TextureFromFile()传入路径加载纹理,和创建纹理一样
-
理解MTL文件
#材质信息
#注释
# Blender MTL File: 'nanosuit.blend'
# Material Count: 6#newmtl < 材质名 >
#手臂
newmtl Arm
Ns 96.078431#高光色的权重
Ka 0.000000 0.000000 0.000000#环境色、漫射色和高光色,分量值的区间为[0.0,1.0]
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000#光学密度
d 1.000000#透明度
illum 2#光照模型
map_Kd arm_dif.png#使用的贴图
map_Bump arm_showroom_ddn.png
map_Ks arm_showroom_spec.png
-
加载自己的模型:
- 导入自己的obj……