网格Mesh

网格(Mesh)代表的是单个的可绘制实体,我们现在先来定义一个我们自己的网格类。 一个网格应该至少需要一系列的顶点,每个顶点包含一个位置向量、一个法向量和一个纹理坐标向量。 一个网格还应该包含用于索引绘制的索引以及纹理形式的材质数据(漫反射/镜面光贴图)。 这些结构是cpu的准备数据封装

  1. 顶点结构 cpp struct Vertex { glm::vec3 Position; glm::vec3 Normal; glm::vec2 TexCoords; };

  2. 纹理结构 cpp struct Texture { unsigned int id; //纹理id string type; //纹理类型 };

  3. 网格Mesh > 准备好顶点和纹理结构,则可以准备mesh结构了

        class Mesh {
            public:
                /*  网格数据  */
                vector<Vertex> vertices;
                vector<unsigned int> indices;
                vector<Texture> textures;
                /*  函数  */
                Mesh(vector<Vertex> vertices, vector<unsigned int> indices, vector<Texture> textures);
                void Draw(Shader shader);
            private:
                /*  渲染数据  */
                unsigned int VAO, VBO, EBO;
                /*  函数  */
                void setupMesh();
        };  
        Mesh(vector<Vertex> vertices, vector<unsigned int> indices, vector<Texture> textures)
        {
            this->vertices = vertices;
            this->indices = indices;
            this->textures = textures;
            //创建绑定设置渲染数据。
            setupMesh();
        }
        void setupMesh()
        {
            glGenVertexArrays(1, &VAO);
            glGenBuffers(1, &VBO);
            glGenBuffers(1, &EBO);
            //bind
            glBindVertexArray(VAO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            //set vertex datas
            glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);  
            //set includies datas
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), 
                         &indices[0], GL_STATIC_DRAW);
            // 顶点位置
            glEnableVertexAttribArray(0);   
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
            // 顶点法线
            glEnableVertexAttribArray(1);   
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
            // 顶点纹理坐标
            glEnableVertexAttribArray(2);   
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
            //结束绑定
            glBindVertexArray(0);
        }  
        void Draw(Shader shader) 
        {
            unsigned int diffuseNr = 1;
            unsigned int specularNr = 1;
            for(unsigned int i = 0; i < textures.size(); i++)
            {
                glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
                // 获取纹理序号(diffuse_textureN 中的 N)
                string number;
                string name = textures[i].type;
                if(name == "texture_diffuse")
                    number = std::to_string(diffuseNr++);
                else if(name == "texture_specular")
                    number = std::to_string(specularNr++);
                shader.setFloat(("material." + name + number).c_str(), i);
                glBindTexture(GL_TEXTURE_2D, textures[i].id);
            }
            glActiveTexture(GL_TEXTURE0);
            // 绘制网格
            glBindVertexArray(VAO);
            glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
            glBindVertexArray(0);
        }

文章作者: Yonggang Long
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yonggang Long !
 上一篇
2022-08-10 Yonggang Long
下一篇 
2022-08-10 Yonggang Long
  目录