C++ 在OpenGL中对索引缓冲区对象使用struct会导致segfault
我一直在使用C++ 在OpenGL中对索引缓冲区对象使用struct会导致segfault,c++,c,opengl,struct,valgrind,C++,C,Opengl,Struct,Valgrind,我一直在使用std::vector存储顶点属性,一切都很好,渲染了各种不同的网格。但是经过重构,使我的顶点属性存储在一个结构中,我无法得到最简单的东西来渲染。以下是结构(简化): 我有两个std::vector,一个用于存储顶点属性,另一个用于索引: std::vector<GLushort> indices; std::vector<struct Vertex> vertices; 然后绑定缓冲区: glGenBuffers(1, &ibo_elements)
std::vector
存储顶点属性,一切都很好,渲染了各种不同的网格。但是经过重构,使我的顶点属性存储在一个结构中,我无法得到最简单的东西来渲染。以下是结构(简化):
我有两个std::vector
,一个用于存储顶点属性,另一个用于索引:
std::vector<GLushort> indices;
std::vector<struct Vertex> vertices;
然后绑定缓冲区:
glGenBuffers(1, &ibo_elements);
glBindBuffer(GL_ARRAY_BUFFER, ibo_elements);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(struct Vertex), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
然后在设置着色器程序和绑定属性名称后,我使用glutDisplayFunc
运行此回调:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
void onDisplay()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glBindBuffer(GL_ARRAY_BUFFER, ibo_elements);
glVertexAttribPointer(
attribute_v_coord,
3,
GL_FLOAT,
GL_FALSE,
sizeof(struct Vertex),
BUFFER_OFFSET(0)
);
glEnableVertexAttribArray(attribute_v_coord);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
attribute_v_color,
4,
GL_FLOAT,
GL_FALSE,
sizeof(struct Vertex),
BUFFER_OFFSET(sizeof(GLfloat)*3)
);
glEnableVertexAttribArray(attribute_v_color);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(attribute_v_coord);
glDisableVertexAttribArray(attribute_v_color);
glutSwapBuffers();
}
一切都和我以前的工作非常相似。所以我猜这与数据结构的变化有关。Valgrind显示此错误:
==5382== Invalid read of size 4
==5382== at 0x404EF6A: ??? (in /tmp/glR69wrn (deleted))
==5382== by 0x870E8A9: ??? (in /usr/lib/libnvidia-glcore.so.325.15)
==5382== by 0x200000003: ???
==5382== by 0x404EEBF: ??? (in /tmp/glR69wrn (deleted))
==5382== by 0x2: ???
==5382== by 0xAFFC09F: ???
==5382== by 0x41314D3: ???
==5382== by 0x40E6FFF: ??? (in /dev/nvidia0)
==5382== by 0xFFFFFFFE: ???
==5382== Address 0x28 is not stack'd, malloc'd or (recently) free'd
我是否没有正确定义顶点属性指针?看起来OpenGL正在尝试读取从未正确设置的浮点值
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
另外,当你打印出尺寸时,你会得到什么
我还习惯于在不需要时解开缓冲区:
glBindBuffer(GL_ARRAY_BUFFER, 0); //etc
最后
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); //what's colorbuffer?
(既然您是从同一个ibo_元素缓冲区交错,那么这一行是否应该在这里?在这种情况下,您应该为每个顶点属性指针使用一个VBO。您提供的是一个具有交错数据的单一数据存储。您所需要做的就是更改设置顶点属性指针的调用,以便它们具有正确的步长和基偏移地址。因此,这个“colorbuffer”VBO(这是一个糟糕的名称选择,因为OpenGL已经有了一个叫做colorbuffer的东西)很可能是问题的根源 另一个问题,正如其他地方提到的,是元素索引从1开始。在本例中有3个顶点,元素缓冲区应填充0,1,2的一些组合。元素缓冲区中有3将导致绘制时出现未定义的行为。如果使用无效的索引,很多时候驱动程序不会崩溃,不幸的是,GL没有索引越界的错误状态。通常情况下,您只知道在这种情况下出现了问题,因为屏幕上出现了垃圾 我担心的是,如果不从GL状态机查询信息,您甚至不知道IBO中有多少元素。很抱歉,这是糟糕的应用程序设计。你应该清楚地知道你想要在手之前画多少元素。无论如何,VBO都应该包装在数据结构或类中(至少包括分配的元素数量),您不希望简单地在不知道缓冲区对象句柄表示什么的情况下到处乱扔
此外,在顶点颜色中使用浮点值可能会造成浪费,您几乎从不需要它们(
GLubyte
和0-255通常工作得很好)。1GLfloat
占用的内存与4GLubytes
一样多,并且您正在使用4GLfloat
。。。如果选择使用xyz而不是xyzw作为顶点位置,则使用4GLubytes
也有助于对齐
在较旧的硬件上,4x GLubyte颜色是硬件T&L的“快速路径”。在较新的硬件上,它们占用的内存更少,因此在几乎所有情况下都是一个胜利:)Hi Reed。您正在测试OpenGL错误吗?下面是我为完成这项工作而编写的一个快速宏。每次调用OpenGL后只需调用glErroCheck()。如果你发现什么,请告诉我。行
glBindBuffer(GL_数组_BUFFER,ibo_元素)代码>非常混乱<代码>GL_元素\数组\缓冲区
是绑定称为“ibo_元素”的东西的唯一逻辑位置。哇,你直接指出了我所有的问题。我将glBindBuffer
中的colorbuffer
更改为ibo\u元素
,并修复了索引
,它成功了!我对OpenGL非常陌生,犯了很多错误。首先,我从1开始索引,因为在.obj格式文件中它就是这样工作的。其次,我对缓冲区对象和顶点属性感到困惑。问题是在教程所说的内容和现在的最佳实践之间存在着太多的不一致。一个VBO比一个属性对应一个要容易得多,但这不是一些源所教的。单个VBO实现可以更干净。对我来说,在连续的内存块中拥有单个顶点的所有属性更有意义。从逻辑上讲,我喜欢考虑vtx[n]。pos和vtx[n]。color,而不是vtx_pos[n]和vtx_color[n]。我只能想象教程介绍了多个VBO的使用,因为它们打算随着时间的推移添加额外的数组(即,从pos开始,下一个教程添加颜色,然后添加法线,然后添加纹理坐标)。如果每个缓冲区只包含一个属性,则不需要跨步和指针偏移的概念。
glBindBuffer(GL_ARRAY_BUFFER, 0); //etc
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); //what's colorbuffer?