3D模型未在屏幕OpenGL上绘制

时间:2019-04-03 19:36:02

标签: c++ opengl assimp

我正在尝试为项目设置一个简单的OpenGL框架,但遇到显示.obj模型对象的问题。据我所知,正在使用assimp很好地加载了对象,应该将所有网格物体都绘制到屏幕上,但是我什么都没看到。

我将引导您完成从加载.obj到绘制它的整个过程。首先,我们需要了解一些文件:

main.cxx

int main() 
{

    Display display(800, 600, "project2");

    Model model("./models/nanosuit/nanosuit.obj");
    Shader shader("./shaders/shader");  
    Texture texture("./textures/wall.jpg");

    int width, height;
    glfwGetWindowSize(display.GetWindow(), &width, &height);
    Camera camera(glm::vec3(0, 0, -5.0f), 45.0f, (float)width/height, 0.1f, 1000.0f); 

    Transform transform;

    while (!display.IsClosed())
    {
        display.ProcessInput();
        display.Clear(0.0f, 0.15f, 0.3f, 1.0f);

        shader.Bind();
        texture.Bind(0);

        shader.Update(transform, camera);
        model.Draw();

        display.Update();
    } 

    return 0;
}

Shader :: Update()

void Shader::Update(const Transform& transform, const Camera& camera)
{
    glm::mat4 trans = camera.GetViewProjection() * transform.GetModel();
    glUniformMatrix4fv(uniforms[TRANSFORM_U], 1, GL_FALSE, &trans[0][0]);
}

顶点着色器

#version 330 core
layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;
layout (location=2) in vec3 normal;

out vec2 texCoord0;
out vec3 normal0;

uniform mat4 transform;

void main() {
    gl_Position = transform * vec4(position, 1.0);
    texCoord0 = texCoord;
    normal0 = (transform * vec4(normal, 0.0)).xyz; 
}

片段着色器

#version 330 core

out vec4 FragColor;
uniform sampler2D diffuse;
in vec2 texCoord0;
in vec3 normal0;

void main() {
    FragColor =     texture(diffuse, texCoord0);
}

我首先将模型加载到我的Model类的构造函数中

Model model("./models/nanosuit/nanosuit.obj");

model.cxx

Model::Model(const std::string& filePath)
{
    Assimp::Importer import;
    const aiScene *scene = import.ReadFile(filePath, aiProcess_Triangulate | aiProcess_FlipUVs);

    if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) 
    {
        std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
        return;
    }
    //directory = filePath.substr(0, filePath.find_last_of('/'));

    processNode(scene->mRootNode, scene);
}


void Model::Draw()
{
    for (unsigned int i = 0; i < meshes.size(); ++i)
        meshes[i].Draw();
}

void Model::processNode(aiNode *node, const aiScene *scene)
{
    for (unsigned int i = 0; i < node->mNumMeshes; ++i)
    {
        aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
        meshes.push_back(processMesh(mesh, scene));
    }
    for (unsigned int i = 0; i < node->mNumChildren; i++)
    {
        processNode(node->mChildren[i], scene);
    }
}

Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene)
{
    std::vector<Vertex> vertices;
    std::vector<unsigned int> indices;

    for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
    {
        glm::vec3 position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
        glm::vec2 texCoords = glm::vec2(0.0f);
        if(mesh->mTextureCoords[0])
            texCoords = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
        glm::vec3 normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);

        Vertex vertex(position, texCoords, normal);

        vertices.push_back(vertex);
    }

    // process indices
    for(unsigned int i = 0; i < mesh->mNumFaces; i++)
    {
        aiFace face = mesh->mFaces[i];
        for(unsigned int j = 0; j < face.mNumIndices; j++)
            indices.push_back(face.mIndices[j]);
    }  

    return Mesh(&vertices[0], vertices.size(), &indices[0], indices.size());
}

依次创建一个网格列表,然后通过调用

在屏幕上绘制网格

Model::Draw()

这是我的网格物体类,供您参考

mesh.cxx

Mesh::Mesh(Vertex *vertices, unsigned int numVertices, unsigned int* indices, unsigned int numIndices)
{
    std::vector<glm::vec3> positions;
    std::vector<glm::vec2> texCoords;
    std::vector<glm::vec3> normals;

    for (unsigned int i = 0; i < numVertices; ++i)
    {
        positions.push_back(vertices[i].GetPos());
        texCoords.push_back(vertices[i].GetTexCoord());
        normals.push_back(vertices[i].GetNormal());
    }

    drawCount = numIndices;

    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(NUM_BUFFERS, VBO);

    // positions
    glBindBuffer(GL_ARRAY_BUFFER, VBO[POSITION_VB]);
    glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(positions[0]), &positions[0], GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    // texCoords
    glBindBuffer(GL_ARRAY_BUFFER, VBO[TEXCOORD_VB]);
    glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW);

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);

    // normals
    glBindBuffer(GL_ARRAY_BUFFER, VBO[NORMAL_VB]);
    glBufferData(GL_ARRAY_BUFFER, normals.size()  * sizeof(normals[0]), &normals[0], GL_STATIC_DRAW);

    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(2);

    // indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO[INDEX_VB]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(indices[0]), &indices[0], GL_STATIC_DRAW);

    glBindVertexArray(0);
}

Mesh::~Mesh()
{
    glDeleteVertexArrays(1, &VAO);
}

void Mesh::Draw()
{
    glBindVertexArray(VAO);

    glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_INT, 0);

    glBindVertexArray(0);
}

我已经验证了网格顶点实际上是由Mesh :: Draw()方法接收的,应该绘制它们。但是,再次在窗口中没有输出:(

0 个答案:

没有答案
相关问题