4

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

4

2 回答 2

8

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

是否有任何现代等价于 glBegin/glEnd?它不必调用每个顶点,而是一种我可以在每次更新时发送数据而不将顶点存储在 gpu 中的方法?

基本上不,现代方法是将VAOVBO(和 IBO)一起使用。

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

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

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

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

然后代替使用GL_STATIC_DRAW,然后使用与使用GL_DYNAMIC_DRAW相比,使用它会大大提高 FPS GL_STATIC_DRAW,但这取决于数据量以及更改它的频率。但是尽量限制它,比如如果你实际上不需要,不要更新缓冲区中的数据。

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

于 2013-10-28T07:26:56.557 回答
1

寻找您想要实现的 VAO / VBO 用法。
下面的 C/C++ 代码是一个简单的示例。
输入变量模式是GL_POINTS/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 上,如果满足正确的情况)

如果您还想要着色器,请参阅我的:

于 2013-10-28T07:29:39.967 回答