Loading model
介绍
Assimp 一个模型导入库的介绍,通常OpenGL所能用到的最小的渲染单元应该是mesh,一个model由多个mesh组成。
A single mesh is the minimal representation of what we need to draw an object in OpenGL (vertex data, indices and material properties). A model (usually) consists of several meshes.
mesh
初始化
核心是mesh类和几个数据结构体
注意,结构体在cpp内存中是连续的,这是个很重要的点。
比如,这个是等价的:
Vertex vertex;
vertex.Position  = glm::vec3(0.2f, 0.4f, 0.6f);
vertex.Normal    = glm::vec3(0.0f, 1.0f, 0.0f);
vertex.TexCoords = glm::vec2(1.0f, 0.0f);
// = [0.2f, 0.4f, 0.6f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f];
渲染
核心问题,不知道有多少个texture,我们在mesh.h中实现绘制mesh方法的时候,可以根据texture数组的size和type来确定有多少个什么样子的shader,然后经过字符处理将它传给shader。注意shader中我们可以定义很多texture,但是不一定都用到。。占存储空间吗?
代码
1  | struct Vertex {  | 
Model
这两天过OpenGL的这个过程中才发现,一个好的设计思路和清晰的思维比代码能力(我指的是编码能力)重要多了,这个的能力基础就是对IO、数据结构、算法、内存、显存、整个架构的正确理解。比如,我们这里要加载模型,根据模型文件的定义,我们核心要处理的是mesh。上一节,mesh搞定了,基于此我们来想model应该做什么:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Model 
{
    public:
        /*  Functions   */
        Model(char *path)
        {
            loadModel(path);
        }
        void Draw(Shader shader);	
    private:
        /*  Model Data  */
        vector<Mesh> meshes;
        string directory;
        /*  Functions   */
        void loadModel(string path);
        void processNode(aiNode *node, const aiScene *scene);
        Mesh processMesh(aiMesh *mesh, const aiScene *scene);
        vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type, 
                                             string typeName);
};
剩下的实现,就是经验的问题了。
加载贴图的优化
这里需要主义的问题是,一个贴图资源,很有可能很多的模型都在用,所以避免重复加载资源或者优化处理比较重要。这是模型加载的性能瓶颈。
怎么解决呢,我们把已经加载的texture在global空间存起来,每次加载前先看是不是已经加载过了。
代码
1  | unsigned int TextureFromFile(const char *path, const string &directory, bool gamma = false);  | 
整体结构
1  | 
  |