调用glDrawArrays后出现SegFault
SegFault after calling glDrawArrays
我正在尝试编写一个sprite批处理程序。最初,我将以下数据上传到openGL,以查看是否可以在屏幕上显示任何内容:
static GLfloat const vertexData[] = {
//Position //Color //UV Coords
0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f
};
这些是我的顶点和片段着色器:
const char* vert = "#version 330 coren"
"layout (location = 0) in vec2 vPos;n"
"layout (location = 1) in vec4 vColor;n"
"layout (location = 2) in vec2 vTexPos;n"
"n"
"out vec4 fColor;n"
"out vec2 fTexPos;n"
"n"
"void main() {n"
" gl_Position = vec4(vPos.xy, 0.0, 1.0);n"
" fColor = vColor;n"
" fTexPos = vec2(vTexPos.s, 1.0 - vTexPos.t);n"
"}";
const char* frag = "#version 330 coren"
"in vec4 fColor;n"
"in vec2 fTexPos;n"
"out vec4 finalColor;n"
"n"
"uniform sampler2D textureUniform;n"
"n"
"void main() {n"
" vec4 textureColor = texture(textureUniform, fTexPos);"
" finalColor = fColor * textureColor;n"
"}";
我这样设置VAO和VBO:
auto vaoID_ = 0;
auto vboID_ = 0;
glGenVertexArrays(1, &vaoID_);
glGenBuffers(1, &vboID_);
glBindVertexArray(vaoID_);
glBindBuffer(GL_ARRAY_BUFFER, vboID_);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV
最后,在每个循环中,我都会孤立缓冲区,然后将数据放入
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexData), vertexData);
glDrawArrays(GL_TRIANGLES, 0, 6);
这很好!因此,我尝试开始编写一个基本的sprite批处理。我将顶点数据分组到POD结构中:
struct VertexData {
struct {
GLfloat screenx;
GLfloat screeny;
} position;
struct {
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat a;
} color;
struct {
GLfloat texu;
GLfloat texv;
} uv;
}
并使用一个向量将所有内容批处理在一起:std::vector<VertexData> spritebatch_
我更改了对glVertexAttribPointer
的调用以匹配此结构(尽管我认为此更改是不必要的?)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV
为了测试它,在每个循环中,我都会向它提供与静态GLfloat
阵列中相同的数据:
spritebatch_.push_back({0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});
spritebatch_.push_back({-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});
然后尝试孤立缓冲区并将数据放入:
glBufferData(GL_VERTEX_ARRAY, spritebatch_.size() * sizeof(VertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_VERTEX_ARRAY, 0, spritebatch_.size() * sizeof(VertexData), spritebatch_.data());
glDrawArrays(GL_TRIANGLES, 0, spritebatch_.size());
最后,我将重置spritebatch_:spritebatch_.clear();
然而,这是错误的。当我孤立缓冲区并将数据放入时,我是否做了不正确的事情?数据格式仍然匹配(VertexData
POD成员仍然都是GLfloat
),spritebatch_
的大小仍然是6(6个顶点组成一个正方形),并且数据在每个顶点内的位置仍然相同。
glVertexAttribPointer
的第五个参数是"步幅",即连续通用顶点属性之间的字节偏移。
所以的变化
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV
到
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV
很重要,因为sizeof(VertexData)
不是8,而是8*sizeof(GL_FLOAT)
。
glBufferData
和glBufferSubData
的第一个参数必须是目标的枚举器常数,它是GL_ARRAY_BUFFER
、GL_ELEMENT_ARRAY_BUFFER
、…之一GL_VERTEX_ARRAY
标识固定功能客户端功能的顶点数组-请参见glEnableClientState
。
更改:
glBufferData(GL_VERTEX_ARRAY, ...);
glBufferData(GL_ARRAY_BUFFER, ...);
glBufferSubData(GL_VERTEX_ARRAY, ...);
glBufferSubData(GL_ARRAY_BUFFER, ...);
注意,如果要检查OpenGL错误(glGetError
或调试输出),则会得到GL_INVALID_ENUM
错误
未创建数组缓冲区的数据存储,这会导致段故障。
- C++中带有List类的迭代器Segfault
- 使用Vulkan hpp vk::enumerateInstanceVersion()会导致segfault
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- std::partition segfault issue
- OpenSSL: EC_POINT_set_compressed_coordinates_GFp segfault
- 检查nullptr是否100%保护内存布局不受segfault影响
- OpenCV Tracker 属性访问在 ARM 上因 SEGFAULT 而失败,但在 X86_64 中工作
- 为什么优化大型 std::vector 数组会导致 SegFault?
- C++segfault,可重复的例子
- 带有zip_source_buffer的libzip会导致数据损坏和/或segfault
- 导致SegFault C++的析构函数
- 从引用的Vector获取SEGFAULT
- 尝试读取/写入Graphviz DAG值的工作证明会导致segfault
- Segfault如果更改派生类的指针值
- SegFault deleting QTreeWidgetItem
- PyImport_Import segfault
- 添加#pragma循环后出现Segfault
- 使用 gmock 时的 SegFault
- C 多线程,在并行多个线程时获得SegFault
- 使用std :: to_string()创建std :: String时的segfault