OpenGL 3.3:调用 glBindBuffer 时 GL_INVALID_OPERATION
OpenGL 3.3: GL_INVALID_OPERATION when calling glBindBuffer
好的,所以我在设置 OpenGL 代码时遇到了一个非常棘手的问题。我正在尝试将我的图形代码重构为渲染器对象,但我似乎无法深入了解棘手的 GL_INVALID_OPERATION 错误(代码 1282)。
我首先创建一个网格对象,该对象初始化松散定义的 OpenGL 对象集合,并以 RAII 风格管理它们的生命周期:
struct OpenGLMesh
{
OpenGLMesh(OpenGLRenderer& renderer,
int shader_index,
const char* fpath);
~OpenGLMesh();
GLuint vbo_;
GLuint ebo_;
GLuint texture_;
std::vector<float> vertices_;
std::vector<unsigned int> indices_;
GLuint shader_id_;
GLuint mvp_id_;
};
OpenGLMesh::OpenGLMesh(OpenGLRenderer& renderer, int shader_index, const char* fpath)
{
glGenBuffers(1, &vbo_);
glGenBuffers(1, &ebo_);
glGenTextures(1, &texture_);
renderer.loadTexture(*this, fpath);
const std::vector<GLuint>& shaders = renderer.getShaders();
shader_id_ = shaders.at(shader_index);
mvp_id_ = glGetUniformLocation(shader_id_, "MVP");
}
OpenGLMesh::~OpenGLMesh()
{
glDeleteBuffers(1, &vbo_);
glDeleteBuffers(1, &ebo_);
glDeleteTextures(1, &texture_);
}
同时我有一个渲染器对象,它拥有大部分初始化和渲染函数。例如,上面构造函数中的 loadTexture 函数是我的 OpenGLRenderer class:
的一部分
OpenGLRenderer::OpenGLRenderer()
{
glGenVertexArrays(1, &vao_); // allocate + assign a VAO to our handle
shaders_.push_back(loadShaders("shaders/texture.vert", "shaders/texture.frag"));
}
OpenGLRenderer::~OpenGLRenderer()
{
std::vector<GLuint>::iterator it;
for (it = shaders_.begin(); it != shaders_.end(); ++it)
{
glDeleteProgram(*it);
}
glDeleteVertexArrays(1, &vao_);
}
我首先担心的是,这些函数调用的划分可能以某种方式使我的 OpenGL 设置调用的某些部分无效。但是,在我尝试绑定网格的 VBO 之前,错误不会出现。
下面是我为调试此问题而构建的精简测试模块中的代码:
// create the renderer object
OpenGLRenderer renderer;
// create and store a mesh object
std::vector<OpenGLMesh> meshes;
meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
// SDL Event handling loop
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao_);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo_);
printOpenGLError(); // prints out error code 1282
我已经确认每次都是这条线中断,尽管它似乎直到循环的下一次迭代才发出终止信号。
我无法找到关于此问题的任何见解 - 似乎 glBindBuffer 通常不会生成此类错误。我还确保 mesh.vbo_ ID 仍指向同一位置。
出于某种原因,我的应用程序的堆栈跟踪不能很好地与 GDB 配合使用,因此我无法像往常一样查看跟踪。任何建议都会有所帮助,从调试技巧到可能的故障源 - 提前致谢!
(这是我的第一个真正的 post,如果我搞砸了什么,请告诉我!)
它是 calss 的构造函数 OpenGLMesh
生成对象缓冲区 (glGenBuffers
)。在析构函数中 OpenGLMesh::~OpenGLMesh
对象缓冲区被销毁 (glDeleteBuffers
).
在下一行中:
meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
你push_back
OpenGLMesh
来了std::vector
。这意味着生成了一个临时 OpenGLMesh
对象,并在其构造函数中生成了对象缓冲区。此时所有数据都是有效的,并且生成了对象缓冲区(GPU)。当调用std::vector::push_back
时,会在std::vector
中生成一个新的OpenGLMesh
对象。该对象由默认的复制构造函数构造,并获得第一个 OpenGLMesh
对象的所有成员的副本。完成后,临时 OpenGLMesh
对象立即被销毁,对象缓冲区被临时对象的析构函数 OpenGLMesh::~OpenGLMesh
删除 (glDeleteBuffers
)。此时所有数据都没有了。
参见 std::vector::push_back
。在析构函数中打个断点OpenGLMesh::~OpenGLMesh
,然后就可以简单的跟踪过期了。
您应该使 class not 可复制且 not 可复制构造,但指定移动构造函数和移动运算符。
class OpenGLMesh
{
OpenGLMesh(const OpenGLMesh &) = delete;
OpenGLMesh & operator = (const OpenGLMesh &) = delete;
OpenGLMesh( OpenGLMesh && );
OpenGLMesh & operator = ( OpenGLMesh && );
....
};
出于调试原因,您可以通过替换
来快速修复此行为
meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
来自
meshes.emplace_back(renderer, 0, "./assets/dune_glitch.png");
(参见 std::vector::emplace_back
)
有关移动构造函数和移动运算符的实现,请参阅:
好的,所以我在设置 OpenGL 代码时遇到了一个非常棘手的问题。我正在尝试将我的图形代码重构为渲染器对象,但我似乎无法深入了解棘手的 GL_INVALID_OPERATION 错误(代码 1282)。
我首先创建一个网格对象,该对象初始化松散定义的 OpenGL 对象集合,并以 RAII 风格管理它们的生命周期:
struct OpenGLMesh
{
OpenGLMesh(OpenGLRenderer& renderer,
int shader_index,
const char* fpath);
~OpenGLMesh();
GLuint vbo_;
GLuint ebo_;
GLuint texture_;
std::vector<float> vertices_;
std::vector<unsigned int> indices_;
GLuint shader_id_;
GLuint mvp_id_;
};
OpenGLMesh::OpenGLMesh(OpenGLRenderer& renderer, int shader_index, const char* fpath)
{
glGenBuffers(1, &vbo_);
glGenBuffers(1, &ebo_);
glGenTextures(1, &texture_);
renderer.loadTexture(*this, fpath);
const std::vector<GLuint>& shaders = renderer.getShaders();
shader_id_ = shaders.at(shader_index);
mvp_id_ = glGetUniformLocation(shader_id_, "MVP");
}
OpenGLMesh::~OpenGLMesh()
{
glDeleteBuffers(1, &vbo_);
glDeleteBuffers(1, &ebo_);
glDeleteTextures(1, &texture_);
}
同时我有一个渲染器对象,它拥有大部分初始化和渲染函数。例如,上面构造函数中的 loadTexture 函数是我的 OpenGLRenderer class:
的一部分OpenGLRenderer::OpenGLRenderer()
{
glGenVertexArrays(1, &vao_); // allocate + assign a VAO to our handle
shaders_.push_back(loadShaders("shaders/texture.vert", "shaders/texture.frag"));
}
OpenGLRenderer::~OpenGLRenderer()
{
std::vector<GLuint>::iterator it;
for (it = shaders_.begin(); it != shaders_.end(); ++it)
{
glDeleteProgram(*it);
}
glDeleteVertexArrays(1, &vao_);
}
我首先担心的是,这些函数调用的划分可能以某种方式使我的 OpenGL 设置调用的某些部分无效。但是,在我尝试绑定网格的 VBO 之前,错误不会出现。
下面是我为调试此问题而构建的精简测试模块中的代码:
// create the renderer object
OpenGLRenderer renderer;
// create and store a mesh object
std::vector<OpenGLMesh> meshes;
meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
// SDL Event handling loop
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao_);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo_);
printOpenGLError(); // prints out error code 1282
我已经确认每次都是这条线中断,尽管它似乎直到循环的下一次迭代才发出终止信号。
我无法找到关于此问题的任何见解 - 似乎 glBindBuffer 通常不会生成此类错误。我还确保 mesh.vbo_ ID 仍指向同一位置。
出于某种原因,我的应用程序的堆栈跟踪不能很好地与 GDB 配合使用,因此我无法像往常一样查看跟踪。任何建议都会有所帮助,从调试技巧到可能的故障源 - 提前致谢!
(这是我的第一个真正的 post,如果我搞砸了什么,请告诉我!)
它是 calss 的构造函数 OpenGLMesh
生成对象缓冲区 (glGenBuffers
)。在析构函数中 OpenGLMesh::~OpenGLMesh
对象缓冲区被销毁 (glDeleteBuffers
).
在下一行中:
meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
你push_back
OpenGLMesh
来了std::vector
。这意味着生成了一个临时 OpenGLMesh
对象,并在其构造函数中生成了对象缓冲区。此时所有数据都是有效的,并且生成了对象缓冲区(GPU)。当调用std::vector::push_back
时,会在std::vector
中生成一个新的OpenGLMesh
对象。该对象由默认的复制构造函数构造,并获得第一个 OpenGLMesh
对象的所有成员的副本。完成后,临时 OpenGLMesh
对象立即被销毁,对象缓冲区被临时对象的析构函数 OpenGLMesh::~OpenGLMesh
删除 (glDeleteBuffers
)。此时所有数据都没有了。
参见 std::vector::push_back
。在析构函数中打个断点OpenGLMesh::~OpenGLMesh
,然后就可以简单的跟踪过期了。
您应该使 class not 可复制且 not 可复制构造,但指定移动构造函数和移动运算符。
class OpenGLMesh
{
OpenGLMesh(const OpenGLMesh &) = delete;
OpenGLMesh & operator = (const OpenGLMesh &) = delete;
OpenGLMesh( OpenGLMesh && );
OpenGLMesh & operator = ( OpenGLMesh && );
....
};
出于调试原因,您可以通过替换
来快速修复此行为meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
来自
meshes.emplace_back(renderer, 0, "./assets/dune_glitch.png");
(参见 std::vector::emplace_back
)
有关移动构造函数和移动运算符的实现,请参阅: