在现代OpenGL中无法将自己创建的模型与加载的模型一起渲染

efzxgjgh  于 2022-10-18  发布在  其他
关注(0)|答案(1)|浏览(156)

我无法使用加载的obj同时渲染我自己创建的模型。我有专为加载对象而设计的Mesh.h:

struct Vertex {
    glm::vec3 Position;
    glm::vec3 Normal;
};   
struct Light {
    glm::vec3 position;
    glm::vec3 ambient;
    float diffuse;
    float specular;
};
struct Material {
    float shininess;
    glm::vec3 ambient;
    glm::vec3 diffuse;
    glm::vec3 specular;
};

class Mesh {
public:
    vector<Vertex>       vertices;
    vector<unsigned int> indices;
    Material material;
    unsigned int VAO;

    Mesh(vector<Vertex> vertices, vector<unsigned int> indices, Material material)
    {
        this->vertices = vertices;
        this->indices = indices;
        this->material = material;
        setupMesh();
    }

    void Draw(Shader &shader, Camera &camera)
    {
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float) 1024 / (float) 768, 0.1f,
                                                2000.0f);
        glm::mat4 view = camera.GetViewMatrix();
        shader.setMat4("projection", projection);
        shader.setMat4("view", view);

        shader.setFloat("material.shininess", material.shininess);
        shader.setVec3("material.ambient", material.ambient);
        shader.setVec3("material.diffuse", material.diffuse);
        shader.setVec3("material.specular", material.specular);
        shader.setVec3("light.direction", -camera.Position);
        shader.setVec3("viewPos", camera.Position);
        shader.setVec3("light.ambient", 1.0f, 1.0f, 1.0f);
        shader.setVec3("light.diffuse", 0.8f, 0.8f, 0.8f);
        shader.setVec3("light.specular", 0.8f, 0.8f, 0.8f);

        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(indices.size()), GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
    }

private:
    unsigned int VBO, EBO;

    void setupMesh()
    {
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);

        glBindVertexArray(VAO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
        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));
    }
};

用于绘制对象的Model.h和Main:

void Draw(Shader &shader, Camera &camera)
    {
        shader.use();
        for(unsigned int i = 0; i < meshes.size(); i++)
            meshes[i].Draw(shader, camera);
    }
  while (!glfwWindowShouldClose(window))
    {
        processInput(window, unitBox.size_x(), unitBox.size_y(), unitBox.size_z());
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        for (auto & modelMatrice : modelMatrices)
        {
            ourShader.setMat4("model", modelMatrice);
            moleculeModel.Draw(ourShader, camera);
        }
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();

现在,我想同时绘制和加载我的自定义模型Cube。我创建了一个单独的类cubeMesh.h:

class BoxMesh
{
public:
unsigned int VAO;
std::vector<float> boxVertices = {
        -0.5f, -0.5f, 0.0f,  0.0f,  0.0f, -1.0f,
        0.5f, -0.5f, 0.0f,  0.0f,  0.0f, -1.0f,
        0.5f,  0.5f, 0.0f,  0.0f,  0.0f, -1.0f,
        0.5f,  0.5f, 0.0f,  0.0f,  0.0f, -1.0f,
        -0.5f,  0.5f, 0.0f,  0.0f,  0.0f, -1.0f,
        -0.5f, -0.5f, 0.0f,  0.0f,  0.0f, -1.0f,

        -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,
        0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,
        0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,
        -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,
        -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,

        -0.5f,  0.5f,  1.0f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f, 0.0f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, 0.0f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, 0.0f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f,  1.0f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f,  1.0f, -1.0f,  0.0f,  0.0f,

        0.5f,  0.5f,  1.0f,  1.0f,  0.0f,  0.0f,
        0.5f,  0.5f, 0.0f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, 0.0f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, 0.0f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, 1.0f,  1.0f,  0.0f,  0.0f,
        0.5f,  0.5f, 1.0f,  1.0f,  0.0f,  0.0f,

        -0.5f, -0.5f, 0.0f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f, 0.0f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f,  1.0f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f,  1.0f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f,  1.0f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f, 0.0f,  0.0f, -1.0f,  0.0f,

        -0.5f,  0.5f, 0.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f, 0.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  1.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  1.0f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f,  1.0f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f, 0.0f,  0.0f,  1.0f,  0.0f
};
BoxMesh()
{
    setupBox();
}

void Draw(Shader &shader, Camera &camera)
{
    glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float) 1024 / (float) 768, 0.1f,
                                            2000.0f);
    glm::mat4 view = camera.GetViewMatrix();
    shader.setMat4("projection", projection);
    shader.setMat4("view", view);

    shader.setFloat("material.shininess", 1.0f);
    shader.setVec3("material.ambient",1.0f, 1.0f, 1.0f);
    shader.setVec3("material.diffuse", 1.0f, 1.0f, 1.0f);
    shader.setVec3("material.specular", 1.0f, 1.0f, 1.0f);
    shader.setVec3("light.direction", -camera.Position);
    shader.setVec3("viewPos", camera.Position);
    shader.setVec3("light.ambient", 1.0f, 1.0f, 1.0f);
    shader.setVec3("light.diffuse", 0.8f, 0.8f, 0.8f);
    shader.setVec3("light.specular", 0.8f, 0.8f, 0.8f);

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);

}

private:
    unsigned int VBO;
    void setupBox()
{
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, boxVertices.size() * sizeof(boxVertices), &boxVertices[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
}
};

我预计它会画出一个立方体+许多加载的模型:

while (!glfwWindowShouldClose(window))
    {
        processInput(window, unitBox.size_x(), unitBox.size_y(), unitBox.size_z());
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        for (auto & modelMatrice : modelMatrices)
        {
            ourShader.setMat4("model", modelMatrice);
            moleculeModel.Draw(ourShader, camera);
        }

        BoxMesh box;
        box.Draw(ourShader, camera);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();

然而,我失败了,在哪里?

41ik7eoe

41ik7eoe1#

您将在每一帧中创建对象BoxMesh以及相应的VAO和VBO。除了性能损失,VAO和VBO永远不会被删除,这会导致在每一帧中创建新的对象,并耗尽内存直到结束。应该在应用程序循环之前示例化BoxMesh。你只需要在绘制网格之前绑定Vao即可。
由于box似乎没有模型矩阵,因此必须设置单位矩阵,否则最近绘制的网格的矩阵将在着色器的默认统一块中声明:

class BoxMesh {
public:
    // [...]

    void Draw(Shader &shader, Camera &camera)
    {
        // [...]

        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
BoxMesh box;

while (!glfwWindowShouldClose(window))
{
    // [...]

    ourShader.setMat4("model", glm:mat4(1.0f));
    box.Draw(ourShader, camera);

    // [...]
}

相关问题