我正在为OpenGL构建一个图形API,它基于基本的call-to-draw图形样式。基本上,不是将数据存储到GPU中,而是使用它的句柄调用它,而是提供信息以绘制每次更新应该绘制的内容。我知道它很慢,但它很简单,适用于非性能关键应用程序。无论如何,有没有现代的glBegin / glEnd?它不需要调用每个顶点,但是我可以在每次更新时发送数据,而不将顶点存储在gpu中?
答案 0 :(得分:5)
你几乎回答了自己的问题。
有没有现代的glBegin / glEnd?它不需要调用每个顶点,但是我可以在每次更新时发送数据,而不将顶点存储在gpu中?
基本上不,现代的方法是将VAOs与VBOs(以及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上实现)