C++ OpenGL 3.3:调用glBindBuffer时GL\u操作无效

C++ OpenGL 3.3:调用glBindBuffer时GL\u操作无效,c++,opengl,graphics,opengl-3,C++,Opengl,Graphics,Opengl 3,好的,所以我在设置OpenGL代码时遇到了一个相当棘手的问题。我试图将我的图形代码重构为渲染器对象,但我似乎无法弄清一个棘手的GL_INVALID_操作错误(代码1282)的根源 我首先创建一个网格对象,该对象初始化一个松散定义的OpenGL对象集合,并管理它们的寿命,尝试采用RAII样式: struct OpenGLMesh { OpenGLMesh(OpenGLRenderer& renderer, int shader_index,

好的,所以我在设置OpenGL代码时遇到了一个相当棘手的问题。我试图将我的图形代码重构为渲染器对象,但我似乎无法弄清一个棘手的GL_INVALID_操作错误(代码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_);
}
struct OpenGLMesh
{
OpenGLMesh(OpenGLRenderer&renderer,
int shader_索引,
常量字符*fpath);
~OpenGLMesh();
GLuint vbo;
胶合材料;
胶合纹理;
std::向量顶点;
std::向量指数;
GLuint着色器id id;
GLuint mvp_id_;
};
OpenGLMesh::OpenGLMesh(OpenGLRenderer&renderer,int shader_index,const char*fpath)
{
glGenBuffers(1和vbo);
glGenBuffers(1和ebo);
glGenTextures(1和纹理);
renderer.loadTexture(*this,fpath);
const std::vector&shaders=renderer.getShaders();
shader_id_=shaders.at(shader_索引);
mvp_id_=glGetUniformLocation(着色器_id_,“mvp”);
}
OpenGLMesh::~OpenGLMesh()
{
glDeleteBuffers(1和vbo);
glDeleteBuffers(1和ebo);
glDeleteTextures(1和纹理);
}
同时,我有一个renderer对象,它拥有大多数初始化和渲染功能。例如,上述构造函数中的loadTexture函数是my OpenGLRenderer类的一部分:

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_);
}
OpenGLRenderer::OpenGLRenderer()
{
glgenvertexarray(1,&vao);//分配+为我们的句柄分配一个vao
着色器向后推(loadShaders(“shaders/texture.vert”、“shaders/texture.frag”);
}
OpenGLRenderer::~OpenGLRenderer()
{
std::vector::it迭代器;
for(it=shaders_u.begin();it!=shaders_u.end();++it)
{
glDeleteProgram(*it);
}
GLdeleteVertexarray(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
//创建渲染器对象
opengl渲染器;
//创建并存储网格对象
矢量网格;
mesh.push_back(OpenGLMesh(渲染器,0,“./assets/dune_glitch.png”);
//事件处理循环
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glBindVertexArray(vao_);
glBindBuffer(GL_数组_BUFFER,mesh.vbo_);
printOpenGLError();//打印出错误代码1282
我已经验证过,每次断线肯定是这条线,尽管它似乎直到循环的下一次迭代才发出终止信号

我还没有找到关于这个问题的任何见解-似乎glBindBuffer通常不会生成这种错误。我还确保mesh.vbo\uid仍然指向相同的位置

出于某种原因,我的应用程序的堆栈跟踪与GDB不兼容,因此我无法像平时那样多地查看跟踪。任何建议都会有所帮助,从调试提示到可能的故障源——提前感谢


(这是我第一篇真正的帖子,如果我搞砸了,请告诉我!)

它是calss的构造函数
OpenGLMesh
对象缓冲区被生成(
glGenBuffers
)。在析构函数中,
OpenGLMesh::~OpenGLMesh
对象缓冲区被销毁(
glDeleteBuffers
)。

在以下行中:

meshes.push_back(OpenGLMesh(renderer, 0, "./assets/dune_glitch.png"));
您可以
OpenGLMesh
推回
std::vector
。这意味着将生成一个临时的
OpenGLMesh
对象,并在其构造函数中生成一个对象bfers。此时,所有数据都有效,并生成对象缓冲区(GPU)。调用
std::vector::push_back
时,将在
std::vector
中生成一个新的
OpenGLMesh
对象。该对象由默认的复制构造函数构造,并获取第一个
OpenGLMesh
对象的所有成员的副本。完成此操作后,临时对象的析构函数
OpenGLMesh::~OpenGLMesh
会立即销毁临时
OpenGLMesh
对象,并删除对象缓冲区(
glDeleteBuffers
)。此时,所有数据都消失了

看。在destrutor
OpenGLMesh::~OpenGLMesh
中放置一个断点,然后您可以简单地跟踪过期时间

您应该使类不可复制和不可复制,但指定移动构造函数和移动运算符

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"));

(见附件)


有关移动构造函数和移动运算符的实现,请参见:


酷,这已经消除了glBindBuffer中的错误。我会接受它,因为它解决了我眼前的问题,但我也想用它来尝试修复我的项目代码-你介意我回头看看吗?另外,为了确认,如果我将网格对象作为参数传递给构造函数,这种解构也会发生?无论如何,谢谢你的快速回复!酷,我来看看这些。我不知道复制构造函数称为析构函数,但这是有道理的。这是我之前调试时没有检查的少数几个地方之一,因为我认为这是安全的。再次感谢您的帮助。刚刚找到答案-这是此提示和我的GL\u元素\u数组\u缓冲区数据上的错误大小参数的组合。相关:。
meshes.emplace_back(renderer, 0, "./assets/dune_glitch.png");