【发布时间】:2015-08-07 08:27:22
【问题描述】:
我正在尝试使用 OpenGL 3.3 渲染一个简单的三角形,但是当我调用 glDrawArrays 时,我的程序因分段错误而崩溃。我使用的语言是 C++,我使用库 SDL、glew 和 glm。 我认为发生的事情是,绘图调用试图访问不属于我设置的顶点缓冲区的数据。 出于无关紧要的原因,我无法提供程序的完整源代码。不过,我可以提供一些相关的 sn-ps 和使用 Apitrace 工具生成的 OpenGL 调用跟踪。
[...]
glClearColor(red = 0, green = 0, blue = 0.5, alpha = 1)
glClear(mask = COLOR_BUFFER_BIT)
glGenVertexArrays(n = 1, arrays = &1)
glBindVertexArray(array = 1)
glGenBuffers(n = 1, buffer = &1)
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 1)
glBufferData(target = GL_ARRAY_BUFFER, size = 72, data = blob(72), usage = GL_STATIC_DRAW)
glVertexAttribPointer(index = 0, size = 3, type = GL_FLOAT, normalized = GL_FALSE, stride = 24, pointer = NULL)
glVertexAttribPointer(index = 1, size = 3, type = GL_FLOAT, normalized = GL_FALSE, stride = 24, pointer = 0xc)
glEnableVertexAttribArray(index = 0)
glEnableVertexAttribArray(index = 1)
glCreateShader(type = GL_VERTEX_SHADER) = 1
glShaderSource(shader = 1, count = 1, string = &"#version 330
layout (location = 0) in vec3 iPosition;
layout (location = 1) in vec3 iNormal;
void main() {
gl_Position = vec4(iPosition.x, iPosition.y, iPosition.z, iNormal.z * -1.0);
}", length = NULL)
glCreateShader(type = GL_FRAGMENT_SHADER) = 2
glShaderSource(shader = 2, count = 1, string = &"#version 330
out vec4 oFragColor;
void main() {
oFragColor = vec4(1.0, 0.0, 0.0, 1.0);
}", length = NULL)
glCompileShader(shader = 1)
glGetShaderiv(shader = 1, pname = GL_COMPILE_STATUS, params = &1)
glCompileShader(shader = 2)
glGetShaderiv(shader = 2, pname = GL_COMPILE_STATUS, params = &1)
glCreateProgram() = 3
glAttachShader(program = 3, shader = 1)
glAttachShader(program = 3, shader = 2)
glBindAttribLocation(program = 3, index = 1, name = "iNormal")
glBindAttribLocation(program = 3, index = 0, name = "iPosition")
glLinkProgram(program = 3)
glGetProgramiv(program = 3, pname = GL_LINK_STATUS, params = &1)
glGetAttribLocation(program = 3, name = "iPosition") = 0
glGetAttribLocation(program = 3, name = "iNormal") = 1
glGetIntegerv(pname = GL_CURRENT_PROGRAM, params = &0)
glUseProgram(program = 3)
glBindVertexArray(array = 1)
glClear(mask = GL_COLOR_BUFFER_BIT)
glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 3) //incomplete (segfault here)
正如我所说,我认为问题在于,绘图调用试图以错误的方式访问数据。我已经使用 glGetBufferSubData 检查了顶点缓冲区中的数据。所以这是我用来设置 VAO 的代码:
Mesh::Mesh(const std::vector<Triangle>& triangles): _vao(0), _vbo(0) {
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
struct Vertex {
glm::vec3 position;
glm::vec3 normal;
}
Vertex* vertecies = new Vertex[triangles.size() * 3];
// [...]
// Convert triangles to vertecies, store them in the array.
glBufferData(GL_ARRAY_BUFFER, triangles.size() * 3 * sizeof(Vertex), vertecies, GL_STATIC_DRAW);
delete[] vertecies;
//Position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(0));
//Normal
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
}
我怀疑错误出在我调用 glVertexAttribPointer 的方式上。 如果程序的其他部分需要回答,请给我留言,我会看看我能做些什么来提供它们。
【问题讨论】:
-
首先,在shader和
glBindAttribLocation调用中绑定不同位置的属性。 (着色器:iPosition = 0,iNormal = 1,glBindAttribLocation:iNormal = 0,iPosition = 1)。 -
这实际上只是我在复制跟踪时犯的一个错误。事实上,我什至从未自己调用 glBindAttribLocation。这似乎是 OpenGL 在着色器中处理 (location = 0) 的方式。