opengl网格绘图不正确

时间:2017-05-05 22:08:59

标签: c++ opengl

为什么我的网格没有正确绘制?我从文件中加载了一个.OBJ模型并尝试绘制它但它总是变形。任何帮助将不胜感激。

这是我的代码:

void Renderer::draw_model(const std::vector<Vector3>& vertex_array, const std::vector<unsigned int>& element_array, const std::vector<Vector2>& uv_array, const std::vector<Vector3>& normal_array, double x, double y, double z, double rx, double ry, double rz, double sx, double sy, double sz, const std::vector<Texture *>& texture_array, double red, double green, double blue, double alpha)
{
#ifdef DOKUN_OPENGL // OpenGL is defined
    if(get_current_rendering_API() != "OpenGL") // but it is not set as the current rendering API
        return;
#ifdef __windows__
    if(!wglGetCurrentContext())
    {
        Logger("Rendering Failed : No OpenGL Context found");
        return;
    }
#endif  
#ifdef __gnu_linux__
#ifdef DOKUN_X11
    if(!glXGetCurrentContext())
    {
        Logger("Rendering failed : No OpenGL Context found");
        return;
    }
#endif
#endif          
    if(vertex_array.empty())
    {
        Logger("Rendering failed : Vertex list is empty!");
        return;
    }
    if(element_array.empty())
    {
        Logger("Rendering failed : Element list is empty!");
        return;     
    }
    const GLchar * vertex_source[] =
    {
        "#version 400\n"
        "layout(location = 0) in vec3 position;\n"
        "layout(location = 1) in vec2 tex_coord;\n" 
        "layout(location = 2) in vec3 normal;\n"
        "                                              \n"
        "                                              \n"
        "                                              \n"
        "uniform mat4 proj;  // zooming                \n"
        "uniform mat4 view;  // camera pos             \n"
        "uniform mat4 model; // object                 \n"
        "                                              \n"
        "                                              \n"
        "                                              \n"  
        "                                              \n"
        "out vec3 Normal  ;\n"
        "out vec2 Texcoord;\n"
        "\n"
        "out vec3 frag_position;\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "void main(void)                               \n"
        "{                                             \n"

            "//frag_position = vec3(model * vec4(position, 1));\n"

            "Texcoord    = tex_coord;\n"
            "Normal      = mat3(transpose(inverse(model))) * normal;//normal;\n"
            "gl_Position = proj * view * model * vec4(position, 1.0);\n"
        "}                                             \n"      
    };          
    const GLchar * fragment_source[] = // holds all color
    {
        "#version 400                                  \n"
        "                                              \n"
        "out vec4 out_color;                           \n"      
        "uniform vec4 color;\n"
        "\n"
        "\n"
        "in vec3 Normal  ;\n"
        "in vec2 Texcoord;\n"
        "\n"
        "in vec3 frag_position;\n"
        "\n"        
        "\n"
        "\n"
        "uniform vec3 light_color ;\n"
        "uniform vec3 light_position;\n"
        "\n"
        "\n"
        "\n"
        "void main(void)                               \n"
        "{                                             \n"
            "\n"
            "vec3 light_direction = normalize(light_position - frag_position);\n"
            "vec3 ambient = 0.1f      * light_color;\n"
            "vec3 diffuse = max(dot(normalize(Normal), light_direction), 0.0)  * light_color;\n"
            "\n"
            "\n"
            "out_color = vec4((ambient + diffuse) * color.xyz, 1.0); \n"
        "}                                             \n"      
    };  
    glEnable(GL_DEPTH_TEST);  // enable depth
    glEnable(GL_CULL_FACE );
    // Set mode     
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // GL_POINT, GL_LINE, GL_FILL, 
    //--------------        
    // shaders
    Shader vertex_shader  ;
    Shader fragment_shader;     
    vertex_shader.create(DOKUN_SHADER_VERTEX);
    vertex_shader.set_source(vertex_source);
    vertex_shader.compile(); 
    fragment_shader.create(DOKUN_SHADER_FRAGMENT);
    fragment_shader.set_source(fragment_source);
    fragment_shader.compile(); 
    // program
    Program program;
    program.create();
    program.attach(vertex_shader  );
    program.attach(fragment_shader);
    program.link();
    // delete shaders after linking them to the program
    vertex_shader.destroy  ();
    fragment_shader.destroy();
    // use program
    program.use ();    
    //---------------
    // set uniforms
    ////////////////////////
    // light
    if(program.get_uniform("light_color" ) != -1) program.set_uniform("light_color", 1.0f, 1.0f, 1.0f);//, (alpha / 255));
    if(program.get_uniform("light_position" ) != -1) program.set_uniform("light_position", 1,1,1);//static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));//, (alpha / 255));
   ////////////////////////     
   // camera
    glm::vec3 eye    = glm::vec3(camera->get_position().x, camera->get_position().y, camera->get_position().z);
    glm::vec3 center = glm::vec3(camera->get_position().x + camera->get_view().x, camera->get_position().y + camera->get_view().y, camera->get_position().z + camera->get_view().z);
    glm::vec3 up     = glm::vec3(camera->get_up().x  , camera->get_up().y  , camera->get_up().z);
   //////////////////////// 
#ifdef use_glm
    glm::mat4 model;
    model = glm::scale(model, glm::vec3(static_cast<float>(sx), 
        static_cast<float>(sy), 
        static_cast<float>(sz)));
    model = glm::rotate(model, static_cast<float>(rx), glm::vec3(1, 0, 0));
    model = glm::rotate(model, static_cast<float>(ry), glm::vec3(0, 1, 0));
    model = glm::rotate(model, static_cast<float>(rz), glm::vec3(0, 0, 1));
    model = glm::translate(model, glm::vec3(static_cast<float>(x), 
        static_cast<float>(y), 
        static_cast<float>(z)));
    glm::mat4 view = glm::lookAt(eye, center, up);  
    glm::mat4 proj = glm::perspective(67.5f, static_cast<float>(800 / 600), 1.0f, 1024.0f); // average fov = 67.5    45 + 90 = 135 / 2 = 67.5 |  znear=1  zfar=1024
    glm::mat4 modelview = model * view;

    glUniformMatrix4fv(glGetUniformLocation((GLuint)program.get_id(), "model"),  1, false, glm::value_ptr(model) ); // object
    glUniformMatrix4fv(glGetUniformLocation((GLuint)program.get_id(), "view"),  1, false, glm::value_ptr(view) );   // camera
    glUniformMatrix4fv(glGetUniformLocation((GLuint)program.get_id(), "proj"),  1, false, glm::value_ptr(proj) );   // zoom
#endif
    ////////////////////////
    if(program.get_uniform("color") != -1) program.set_uniform("color", (red / 255), (green / 255), (blue / 255), (alpha / 255));
    //program.get_default()->set_uniform("base", static_cast<int>(0)); // bind to texture unit 0
    ////////////////////////        
    // texture data
    /*
    GLuint * texture = new GLuint[8]; // 256 would be ideal     
    for(unsigned int i = 0; i < texture_array.size(); i++) // for each texture
    { 
        std::cout << "GENERATING TEXTURES...." << std::endl;
        glGenTextures(8, texture); // generate 256 textures
        glActiveTexture(GL_TEXTURE0 + i);
        glBindTexture( GL_TEXTURE_2D, (GLuint)texture[i] );         
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

        glTexImage2D( GL_TEXTURE_2D, 0,  GL_RGBA, texture_array[i]->get_width(), texture_array[i]->get_height(), 0, GL_RGBA, 
            GL_UNSIGNED_BYTE, texture_array[i]->get_data() ); 
        glGenerateMipmap(GL_TEXTURE_2D);    
    }
    */
    ///////////////////////
    ///////////////////////
    // vertex array obj
    GLuint vertex_array_obj;
    glGenVertexArrays(1, &vertex_array_obj);
    // vertex buffer obj - for drawing
    glBindVertexArray(vertex_array_obj); // bind vertex array obj to vertex attrib ptr
        GLuint vertex_buffer_obj;
        glGenBuffers(1, & vertex_buffer_obj);
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_obj);
        glBufferData(GL_ARRAY_BUFFER, vertex_array.size() , &vertex_array[0], GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_DOUBLE, GL_FALSE, 0, static_cast<void*>(0)); 
    glBindVertexArray(0);               // unbind
    // tex_coord buffer obj - for texture mapping
    GLuint uv_buffer_obj;
    if(!uv_array.empty())
    {
    glBindVertexArray(vertex_array_obj); // bind    
        glGenBuffers(1, & uv_buffer_obj);
        glBindBuffer(GL_ARRAY_BUFFER, uv_buffer_obj);
        glBufferData(GL_ARRAY_BUFFER, uv_array.size() , &uv_array[0], GL_STATIC_DRAW);          
        glEnableVertexAttribArray(1);  
        glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, 0, static_cast<void*>(0));     
    glBindVertexArray(0); // unbind 
    }
    // normal buffer - for lighting
    GLuint normal_buffer_obj;
    if(!normal_array.empty())
    {       
    glBindVertexArray(vertex_array_obj); // bind 
        glGenBuffers(1, & normal_buffer_obj);
        glBindBuffer(GL_ARRAY_BUFFER, normal_buffer_obj);
        glBufferData(GL_ARRAY_BUFFER, normal_array.size(), &normal_array[0], GL_STATIC_DRAW);           
        glEnableVertexAttribArray(2);  
        glVertexAttribPointer(2, 3, GL_DOUBLE, GL_FALSE, 0, static_cast<void*>(0)); 
    glBindVertexArray(0);               // unbind 
    }
    // element buffer - specifies order in which vertices are to be drawn
    glBindVertexArray(vertex_array_obj); // bind
        GLuint index_buffer_obj;
        glGenBuffers(1, & index_buffer_obj);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_obj);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, element_array.size(), &element_array[0], GL_STATIC_DRAW);
    glBindVertexArray(0);
    // Draw the model !
    glBindVertexArray(vertex_array_obj); // bind
        glDrawElements(GL_TRIANGLES, element_array.size(), GL_UNSIGNED_INT, 0);//glDrawElements(GL_TRIANGLES, element_array.size(), GL_UNSIGNED_INT, &element_array[0]);     // elements - order in which vertices are to be drawn
    glBindVertexArray(0);                // unbind
    ////////////////////////    
    // cleanup
    // textures
    //if(texture_array.size() > 0)
    //  glDeleteTextures(8, texture);
    // attributes
    glDisableVertexAttribArray(0); // drawing
    glDisableVertexAttribArray(1); // texture mapping
    glDisableVertexAttribArray(2); // lighting
    // buffers
    glDeleteBuffers(1, & vertex_buffer_obj    );
    glDeleteBuffers(1, & uv_buffer_obj        );    
    glDeleteBuffers(1, & normal_buffer_obj    );
    glDeleteBuffers(1, & index_buffer_obj     );
    // arrays
    glDeleteVertexArrays(1, & vertex_array_obj);
    //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    // program
    program.disable();
#endif
}

这是以下代码的结果:

1 个答案:

答案 0 :(得分:1)

所有glBufferData次调用中的size参数都是错误的。此函数需要 byte 中的数据量,但是例如在此行中提供:

glBufferData(GL_ARRAY_BUFFER, vertex_array.size() , &vertex_array[0], GL_STATIC_DRAW);

作为元素的数量。你真正需要的是这样的:

glBufferData(GL_ARRAY_BUFFER, vertex_array.size() * sizeof(Vector3), &vertex_array[0], GL_STATIC_DRAW);

(假设Vector3恰好包含3个双打)。

作为旁注:以双精度提供顶点信息的情况并不常见。因此,如果没有特殊原因,我建议改为使用float