什么是现代OpenGL相当于glBegin / glEnd

时间:2013-10-28 07:11:30

标签: c++ opengl abstraction immediate-mode

我正在为OpenGL构建一个图形API,它基于基本的call-to-draw图形样式。基本上,不是将数据存储到GPU中,而是使用它的句柄调用它,而是提供信息以绘制每次更新应该绘制的内容。我知道它很慢,但它很简单,适用于非性能关键应用程序。无论如何,有没有现代的glBegin / glEnd?它不需要调用每个顶点,但是我可以在每次更新时发送数据,而不将顶点存储在gpu中?

2 个答案:

答案 0 :(得分:5)

你几乎回答了自己的问题。

  

有没有现代的glBegin / glEnd?它不需要调用每个顶点,但是我可以在每次更新时发送数据,而不将顶点存储在gpu中?

基本上不,现代的方法是将VAOsVBOs(以及IBO)一起使用。

如果您要更改VBO中的数据,请记住您可以更改glBufferData中的mode参数。

  • GL_STREAM_DRAW - 数据存储内容将被修改一次,最多使用几次。

  • GL_STATIC_DRAW - 数据存储内容将被修改一次并多次使用。

  • GL_DYNAMIC_DRAW - 数据存储内容将被重复修改并多次使用。

然后使用GL_STATIC_DRAW而不是使用GL_DYNAMIC_DRAW,与使用GL_STATIC_DRAW相比,这会增加FPS,尽管这取决于数据量,以及您的使用频率更改。但是尽可能地限制它,比如不实际需要更新缓冲区中的数据。

您可以在OpenGL's Wiki click here上阅读有关不同缓冲区的更多信息。

答案 1 :(得分:0)

查找您要实施的VAO / VBO用法 在C / C ++代码中,下面是一个简单的例子 输入变量模式为GL_POINYS / TRIANGLES / QUADS / ....(如在glBegin()中) 这也是GLSL和核心配置文件传递属性的唯一选择(glVertex / glNormal / ...在核心中已知一段时间了)

//------------------------------------------------------------------------------
//--- Open GL VAO example (GLSL) -----------------------------------------------
//------------------------------------------------------------------------------
#ifndef _OpenGL_VAO_example_h
#define _OpenGL_VAO_example_h
//------------------------------------------------------------------------------
GLuint vbo[4]={-1,-1,-1,-1};
GLuint vao[4]={-1,-1,-1,-1};
const float vao_pos[]=
    {
//       x      y     z
     0.75f, 0.75f, 0.0f,
     0.75f,-0.75f, 0.0f,
    -0.75f,-0.75f, 0.0f,
    };
const float vao_col[]=
    {
//      r   g    b
     1.0f,0.0f,0.0f,
     0.0f,1.0f,0.0f,
     0.0f,0.0f,1.0f,
     };
//---------------------------------------------------------------------------
void vao_init()
    {
    glGenVertexArrays(4,vao);
    glGenBuffers(4,vbo);

    glBindVertexArray(vao[0]);
        glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vao_pos),vao_pos,GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);

        glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vao_col),vao_col,GL_STATIC_DRAW);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    }
//---------------------------------------------------------------------------
void vao_exit()
    {
    glDeleteVertexArrays(4,vao);
    glDeleteBuffers(4,vbo);
    }
//---------------------------------------------------------------------------
void vao_draw(GLuint mode)
    {
    void *p=NULL;
    glBindVertexArray(vao[0]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glDrawArrays(mode,0,3);
    glBindVertexArray(0);
    }
//------------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------------
//--- end. ---------------------------------------------------------------------
//------------------------------------------------------------------------------

如果您不想使用GLSL,则必须将代码更改为类似的内容:

//tetraeder
#define V_SIZ 12
#define I_SIZ 6
GLfloat tet_verts[V_SIZ] = { \
-0.5f, -1.0f, -0.86f, \
-0.5f, -1.0f, 0.86f, \
1.0f, -1.0f, 0.0f, \
0.0f, 1.0f, 0.0f};

GLushort tet_index = {3, 0, 1, 2, 3, 0};


void init_buffers() {
    glGenBuffersARB(1, &vertex_buf);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertex_buf);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, V_SIZ*sizeof(GLfloat), tet_verts, GL_STATIC_DRAW_ARB); //upload data

    glGenBuffersARB(1, &index_buf);
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, index_buf);
    glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, I_SIZ*sizeof(GLushort), tet_index, GL_STATIC_DRAW_ARB); //upload data

    return;
}

void draw_buffers() {
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertex_buf);
    glVertexPointer(3, GL_FLOAT, 0, 0); //3 is xyz, last 0 ("pointer") is offset in vertex-array

    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, index_buf);

    glEnableClientState(GL_VERTEX_ARRAY);

    //use indexing
    glDrawElements(GL_TRIANGLE_STRIP, I_SIZ, GL_UNSIGNED_SHORT, 0); //last 0 is offset in element-array

    return;
}

void deinit_buffers() {
    glDeleteBuffersARB(1, &vertex_buf);
    glDeleteBuffersARB(1, &index_buf);

    return;
}

PS。我建议不要使用索引,它通常在我使用的所有卡上慢得多,但当然需要更多的内存。索引也没有很好地实现在驱动程序上有时会出现错误(即使在nVidia上,当然如果满足正确的情况,也会在ATI上实现)