OpenGL 在渲染帧之前崩溃 - VBO
OpenGL crashing before it can render a frame - VBOs
在放弃了缓慢的 glBegin/glEnd 技术之后,我最终决定使用 VBO。经过几个小时的挫折,我终于编译成功了。但这并不意味着它有效。函数"CreateVBO"执行没有错误,但是一旦调用glutMainLoop()
,程序就崩溃了,它甚至没有调用Reshape()
或Render()
函数。
这里是 CreateVBO()
函数:
(注意:"lines" 变量等于 400 万,整个程序只是一个压力测试,用于渲染许多行,然后我才能做一些真正有意义的事情)
void CreateVBO()
{
glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
glBindBuffer=(PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
glBufferData=(PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
glDeleteBuffers=(PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
glMapBuffer=(PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer");
for(float i=0; i<lines*2; i++)
{
t_vertices.push_back(i/9000);
t_vertices.push_back(5 * (((int)i%2)*2-1));
t_vertices.push_back(20);
vert_cols.push_back(0);
vert_cols.push_back(255);
vert_cols.push_back(0);
t_indices.push_back((int)i);
}
glGenBuffers(1, &VertexVBOID);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*t_vertices.size(), &t_vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &IndexVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*t_indices.size(), NULL, GL_STATIC_DRAW);
GLvoid * buf = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
memcpy( (void*)buf, &vert_cols[0], (size_t)(sizeof(float)*vert_cols.size()));
glBindBuffer( GL_ARRAY_BUFFER, 0 );
}
这里是 Render()
函数。我不知道它可能有什么问题,因为程序甚至在调用该函数之前就崩溃了。
void Display()
{
glRotatef(1, 0, 1, 0);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(t_vertices.size(), GL_FLOAT, 0, 0); //The starting point of the VBO, for the vertices
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(vert_cols.size(), GL_FLOAT, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glDrawElements(GL_LINES, lines, GL_UNSIGNED_INT, 0);
glutSwapBuffers();
//Sleep(16);
glutPostRedisplay();
}
您的代码没有意义。
首先,创建足够大的 vertexVBOID
来容纳 t_vertices
向量,并用该数组填充它。
然后,您映射该 VBO 并使用来自 vert_color
向量的数据 覆盖 其中的数据。对于绘图,您指定顶点位置和颜色属性都来自内存中的相同位置 - 因此也可以有效地使用颜色作为位置。
但这不是崩溃的原因。崩溃的主要原因其实有两个:
您创建 IndexVBOID
大到足以容纳您的索引数组,但您从未使用某些数据初始化该缓冲区。您改为指定 NULL
作为数据指针,因此存储已创建,但未初始化。因此,您最终会在该缓冲区中得到一个未定义的内容,并且 GL 在使用该内容进行绘图时将访问任意内存位置。
您的 glVertexPointer
和 glColorPointer
调用是错误的。第一个参数 size
是 而不是 数组的大小。它是 单个向量 的大小,可以是 1、2、3 或 4。你的数组大小可能是其他的,所以这个调用最终会生成一个 GL_INVALID_VALUE
错误,并且根本没有设置属性指针。默认情况下,这些指针为 NULL。
所以最终,您要求 GL 从相对于 NULL 指针的未定义数组索引中提取。那极有可能崩溃。一般来说,它只是未定义的行为,结果可以是任何东西。
此外,您还保留 VertexVBOID
缓冲区 已映射 - 您永远不会取消映射。将缓冲区用作 GL 命令的源或目标是无效的,只要它被映射(除非创建持久映射,这是一个相对较新的功能,并不真正属于这里)。
在放弃了缓慢的 glBegin/glEnd 技术之后,我最终决定使用 VBO。经过几个小时的挫折,我终于编译成功了。但这并不意味着它有效。函数"CreateVBO"执行没有错误,但是一旦调用glutMainLoop()
,程序就崩溃了,它甚至没有调用Reshape()
或Render()
函数。
这里是 CreateVBO()
函数:
(注意:"lines" 变量等于 400 万,整个程序只是一个压力测试,用于渲染许多行,然后我才能做一些真正有意义的事情)
void CreateVBO()
{
glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
glBindBuffer=(PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
glBufferData=(PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
glDeleteBuffers=(PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
glMapBuffer=(PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer");
for(float i=0; i<lines*2; i++)
{
t_vertices.push_back(i/9000);
t_vertices.push_back(5 * (((int)i%2)*2-1));
t_vertices.push_back(20);
vert_cols.push_back(0);
vert_cols.push_back(255);
vert_cols.push_back(0);
t_indices.push_back((int)i);
}
glGenBuffers(1, &VertexVBOID);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*t_vertices.size(), &t_vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &IndexVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*t_indices.size(), NULL, GL_STATIC_DRAW);
GLvoid * buf = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
memcpy( (void*)buf, &vert_cols[0], (size_t)(sizeof(float)*vert_cols.size()));
glBindBuffer( GL_ARRAY_BUFFER, 0 );
}
这里是 Render()
函数。我不知道它可能有什么问题,因为程序甚至在调用该函数之前就崩溃了。
void Display()
{
glRotatef(1, 0, 1, 0);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(t_vertices.size(), GL_FLOAT, 0, 0); //The starting point of the VBO, for the vertices
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(vert_cols.size(), GL_FLOAT, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glDrawElements(GL_LINES, lines, GL_UNSIGNED_INT, 0);
glutSwapBuffers();
//Sleep(16);
glutPostRedisplay();
}
您的代码没有意义。
首先,创建足够大的 vertexVBOID
来容纳 t_vertices
向量,并用该数组填充它。
然后,您映射该 VBO 并使用来自 vert_color
向量的数据 覆盖 其中的数据。对于绘图,您指定顶点位置和颜色属性都来自内存中的相同位置 - 因此也可以有效地使用颜色作为位置。
但这不是崩溃的原因。崩溃的主要原因其实有两个:
您创建
IndexVBOID
大到足以容纳您的索引数组,但您从未使用某些数据初始化该缓冲区。您改为指定NULL
作为数据指针,因此存储已创建,但未初始化。因此,您最终会在该缓冲区中得到一个未定义的内容,并且 GL 在使用该内容进行绘图时将访问任意内存位置。您的
glVertexPointer
和glColorPointer
调用是错误的。第一个参数size
是 而不是 数组的大小。它是 单个向量 的大小,可以是 1、2、3 或 4。你的数组大小可能是其他的,所以这个调用最终会生成一个GL_INVALID_VALUE
错误,并且根本没有设置属性指针。默认情况下,这些指针为 NULL。
所以最终,您要求 GL 从相对于 NULL 指针的未定义数组索引中提取。那极有可能崩溃。一般来说,它只是未定义的行为,结果可以是任何东西。
此外,您还保留 VertexVBOID
缓冲区 已映射 - 您永远不会取消映射。将缓冲区用作 GL 命令的源或目标是无效的,只要它被映射(除非创建持久映射,这是一个相对较新的功能,并不真正属于这里)。