关于c ++:与glBegin / glEnd等效的现代OpenGL是什么

What is the modern OpenGL equivalent to glBegin/glEnd

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


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

is there any modern equivalent to glBegin/glEnd? It doesn't have to a call for every vertex, but a way where I can send the data each update, without storing the vertices in the gpu?

基本上没有,现代的方法是将VAO与VBO(和IBO)一起使用。

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

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

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

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

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

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


查找您要实现的VAO / VBO用法。
在C / C ++代码中,波纹管是一个简单的示例。
输入变量模式为GL_POINTS/TRIANGLES/QUADS/...(与glBegin()相同)
这也是GLSL和核心配置文件传递属性的唯一选项(glVertex/glNormal/...在核心中尚不明了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//------------------------------------------------------------------------------
//--- 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,则必须将代码稍微更改为如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//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上,如果满足正确的情况)

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

  • 完整的GL + GLSL + VAO / VBO C ++示例