C++ GLD组件崩溃(OpenGL 3.2/Windows 7)

C++ GLD组件崩溃(OpenGL 3.2/Windows 7),c++,opengl,opengl-3,glm-math,C++,Opengl,Opengl 3,Glm Math,我试图在OpenGL 3.2中绘制一个简单的四元组,但是当我调用“GLDrawerElements”时,应用程序因“访问冲突读取位置0x00000000”而崩溃 我假设问题在于顶点缓冲区数据是错误的,但我不确定如何修复问题/调试它(OpenGL跟踪将非常棒,但我也不知道如何启用它…) 初始化代码: std::vector<CUShort> Indices; const CUShort IndicesArray[] = { 0, 1, 2, 2, 0, 3 }; for(size_t

我试图在OpenGL 3.2中绘制一个简单的四元组,但是当我调用“GLDrawerElements”时,应用程序因“访问冲突读取位置0x00000000”而崩溃

我假设问题在于顶点缓冲区数据是错误的,但我不确定如何修复问题/调试它(OpenGL跟踪将非常棒,但我也不知道如何启用它…)

初始化代码:

std::vector<CUShort> Indices;
const CUShort IndicesArray[] = { 0, 1, 2, 2, 0, 3 };

for(size_t j = 0; j < 1; j++) {
    for(size_t i = 0; i < sizeof(IndicesArray) / sizeof(*IndicesArray); i++) {
        Indices.push_back(4 * j + IndicesArray[i]);
    }
}

glGenBuffers(1, &m_Elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Indices.size() * sizeof(CUShort), &Indices[0], GL_STATIC_DRAW);

glGenVertexArrays(1, &m_Array);
glBindVertexArray(m_Array);

glGenBuffers(1, &m_Buffer);
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexColorVertex), NULL, GL_DYNAMIC_DRAW);

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_TRUE, sizeof(TexColorVertex), (const GLvoid*)offsetof(TexColorVertex, Color));

glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexColorVertex), (const GLvoid*)offsetof(TexColorVertex, Position));

glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(TexColorVertex), (const GLvoid*)offsetof(TexColorVertex, Texcoord));

glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
顶点结构声明如下:

struct TexColorVertex
{
    TexColorVertex(void) { }
    TexColorVertex(glm::vec2 const& Position, glm::vec2 const& Texcoord) :
        Position(Position), Texcoord(Texcoord)
    { }
    glm::vec2 Position;
    glm::vec2 Texcoord;
    glm::vec4 Color;
};

有人对如何解决这个问题并绘制一个占用一半屏幕的简单四边形有什么建议吗?

在调用glBufferData时,您没有为顶点分配足够的空间。传递sizeof(TexColorVertex),它为1个顶点分配空间。如果要绘制四边形,则需要为4个顶点分配空间,因此应按如下方式更改对glBuffer Data的调用:

glBufferData(GL_ARRAY_BUFFER, 4*sizeof(TexColorVertex), NULL, GL_DYNAMIC_DRAW);
这样,当您随后调用glBufferSubData时,您将不会尝试访问超出范围的GPU内存。

虽然确实会提出一个关于缓冲区分配大小的有效点,但实际上这并不是导致崩溃的原因

问题不在于
glBufferSubData(…)
,而在于调用
glpaurements(…)
。此调用试图取消对NULL指针的引用,该指针是一个红色标志,表示没有任何内容绑定到
GL\u元素\u数组\u缓冲区

如果未将任何内容绑定到
GL\u元素\u数组\u缓冲区
,则传递到
glpaurements(…)
的指针是指向客户端内存的实际指针,而不是缓冲区对象(服务器)内存的偏移量


要了解发生这种情况的原因,请回想顶点阵列对象存储的内容:
  • 顶点属性状态[指针,启用/禁用]
  • 元素数组缓冲区绑定
    GL\u元素数组缓冲区
  • 现在,考虑这两个调用的顺序: 首先将某个对象绑定到
    GL\u ELEMENT\u ARRAY\u BUFFER
    m\u Elements),然后立即绑定一个顶点数组对象(m\u ARRAY),该对象用它内部跟踪的绑定替换刚才绑定的元素数组BUFFER

    你应该考虑<强>(1)< /强>使用VAO持久引用单个元素数组缓冲区或<强>(2)< /强>反转这两个调用的顺序。


    如果顶点数组对象(m_数组)总是与相同的元素数组缓冲区一起使用,那么我建议您使用第一种方法。这可以通过在初始化中移动以下代码来实现:

    glGenVertexArrays (1, &m_Array);
    glBindVertexArray (m_Array);
    
    在之前来:


    使用这种方法,无需在绘图代码中将任何内容显式绑定到
    GL\u ELEMENT\u ARRAY\u BUFFER

    您将
    NULL
    作为索引数组发送到
    gldramements
    @JesusRamos。我相信这是一个偏移量。Opengl从当前绑定的元素数组缓冲区获取索引数据。@Ben它是绑定到顶点数组的偏移数组。在本例中,它应该是一个包含6个索引的数组。值得一提的是,在代码中分配缓冲区时,缓冲区的大小实际上是未知的。因此,在图形代码中使用
    glBufferData(…)
    来孤立旧的缓冲区可能更好。没有内存会泄漏,只要管道中没有引用旧内存的挂起命令,GL就会释放旧内存。事实上,这可能会提供更好的性能,因为它不需要OpenGL暂停管道或复制缓冲区来防止挂起的draw命令使用错误的数据副本。这可以归结为GL中的隐式同步。由于调用
    glBufferSubData(…)
    时,来自多个帧的绘制命令可能仍然不完整,为了防止此调用影响以前的帧,GL必须在后台进行一些同步。如果不在每一帧修改缓冲区现有内存的数据,只需分配新内存,就可以防止修改前一帧所需的内存,从而大大简化了工作。同样,没有任何东西会泄漏,因为在没有任何命令引用旧内存后,它会被释放。这也是非常正确的,但由于Andon M.Coleman的回答修复了崩溃的内存,我将他的回答标记为答案。谢谢你在这一点上的帮助:)这至少摆脱了崩溃,仍然没有画出任何东西,但希望我能找出这一部分:)
    glBindBuffer      (GL_ELEMENT_ARRAY_BUFFER, m_Elements);
    glBindVertexArray (m_Array);
    
    glGenVertexArrays (1, &m_Array);
    glBindVertexArray (m_Array);
    
    glGenBuffers (1, &m_Elements);
    glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, m_Elements);
    glBufferData (GL_ELEMENT_ARRAY_BUFFER, Indices.size() * sizeof(CUShort), &Indices[0], GL_STATIC_DRAW);