2015-05-18 123 views
5

我正在寻找一种很好的方式来渲染具有不同顶点布局的网格对象,而不需要付出很大努力(例如为每个顶点布局定义一个渲染器类)。您可以在下面看到一些不同顶点格式的例子。Opengl - 渲染不同的顶点格式

enum EVertexFormat 
{ 
    VERTEX_FORMAT_UNDEFINED = -1, 
    VERTEX_FORMAT_P1 = 0, 
    VERTEX_FORMAT_P1N1, 
    VERTEX_FORMAT_P1N1UV, 
    VERTEX_FORMAT_P1N1C1, 
    VERTEX_FORMAT_P1N1UVC1, 
}; 

// the simplest possible vertex -- position only 
struct SVertexP1 
{ 
    math::Vector3D m_position;  // position of the vertex 
}; 

struct SVertexP1N1 
{ 
    math::Vector3D m_position;  // position of the vertex 
    math::Vector3D m_normal;  // normal of the vertex 
}; 

// a typical vertex format with position, vertex normal 
// and one set of texture coordinates 
struct SVertexP1N1UV 
{ 
    math::Vector3D m_position;  // position of the vertex 
    math::Vector3D m_normal;  // normal of the vertex 
    math::Vector2D m_uv;   // (u,v) texture coordinate 
}; 

struct SVertexP1N1C1 
{ 
    math::Vector3D m_position;  // position of the vertex 
    math::Vector3D m_normal;  // normal of the vertex 
    uint32_t m_color_u32;   // color of the vertex 
}; 

struct SVertexP1N1UVC1 
{ 
    math::Vector3D m_position;  // position of the vertex 
    math::Vector3D m_normal;  // normal of the vertex 
    math::Vector2D m_uv;   // (u,v) texture coordinate 
    uint32_t m_color_u32;   // color of the vertex 
}; 

背景是,我想渲染不同的对象。它们中的一些是不具有纹理坐标或法线的基元(例如平面,球体)。另一方面,我想呈现更复杂的对象,其中有法线,纹理坐标等。有没有一种智能的方法或设计可以避免编程多个渲染器类,而是使用单个渲染器类?我知道,这也会影响着色器。

回答

3

你可以做的是给你的每个顶点结构一个静态方法,可能被称为EnableVertexAttribArray或类似的东西。在这种静态方法中,假设已经绑定了正确的数组缓冲区,您可以在GL_ARRAY_BUFFER中设置顶点布局。

struct SVertexP1N1 
{ 
    math::Vector3D m_position;  // position of the vertex 
    math::Vector3D m_normal;  // normal of the vertex 
    static void EnableVertexAttribArray() 
    { 
     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SVertexP1N1), (const GLvoid*)offsetof(SVertexP1N1, m_position)); 
     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(SVertexP1N1), (const GLvoid*)offsetof(SVertexP1N1, m_normal)); 
     glEnableVertexAttribArray(0); 
     glEnableVertexAttribArray(1); 
    } 
}; 

然后,您可以根据顶点结构创建一个顶点缓冲区的模板类。例如,

template <class VertexType> class vertex_buffer 
{ 
public: 
    typedef VertexType vertex_type; 

    vertex_buffer() 
    { 
     glGenVertexArrays(1, &m_vao); 
     glGenBuffers(1, &m_vbo); 
     glGenBuffers(1, &m_ibo); 
     glBindVertexArray(m_vao); 
     glBindBuffer(GL_ARRAY_BUFFER, m_vbo); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo); 
     vertex_type::EnableVertexAttribArray(); // <-------- 
     glBindBuffer(GL_ARRAY_BUFFER, 0); 
     glBindVertexArray(0); 
    } 

    ~vertex_buffer() 
    { 
     glDeleteVertexArrays(1, &m_vao); 
     glDeleteBuffers(1, &m_vbo); 
     glDeleteBuffers(1, &m_ibo); 
    } 

    // ... 

    void draw() 
    { 
     glBindVertexArray(m_vao); 
     glBindBuffer(GL_ARRAY_BUFFER, m_vbo); 
     glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, NULL); 
     glBindBuffer(GL_ARRAY_BUFFER, 0); 
     glBindVertexArray(0); 
    } 

private: 
    GLuint m_vao; 
    GLuint m_vbo; 
    GLuint m_ibo; 
    std::vector<vertex_type> m_vertices; 
    std::vector<GLuint> m_indices; 
} 
+0

哦,这是一个不错的主意。谢谢! – bobby