You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行glDrawElements时nvoglv32.dll崩溃,疑与glVertexAttribPointer相关

解决glDrawElements在nvoglv32.dll中崩溃的问题

嗨,这个问题其实挺典型的——你调用glDrawElements触发的访问违规,核心原因是完全没处理索引数据的存储(EBO/IBO),OpenGL找不到合法的索引数据,只能去访问空地址(也就是你代码里最后一个参数传的0),直接就崩了。

咱们拆解下问题:
glDrawElements是基于索引的绘制方式,它要求必须提前把索引数据上传到GPU的元素缓冲区对象(EBO)里,并且在绑定VAO的时候把EBO和VAO关联起来。你的代码只处理了顶点数据的VBO,完全没管索引的事儿,GPU自然找不到索引数据,触发0xC0000005访问违规也就不奇怪了。

另外还有个小问题:你调用glDrawElements时传的索引数量是8,这和立方体顶点的实际需求不匹配——一个立方体需要36个索引才能用GL_TRIANGLES画出6个完整的面(每个面2个三角形),8个索引根本不够,就算EBO没问题,绘制结果也会乱套。

下面是修正后的完整步骤和代码:

1. 补充立方体的索引数据

先定义正确的索引数组,对应你提供的8个顶点:

// 立方体的索引数据,共36个索引,对应6个面的12个三角形
GLuint indices[] = {
    0, 1, 2, 0, 2, 3, // 前面
    3, 2, 4, 3, 4, 5, // 右面
    5, 4, 6, 5, 6, 7, // 后面
    7, 6, 1, 7, 1, 0, // 左面
    1, 6, 4, 1, 4, 2, // 上面
    7, 0, 3, 7, 3, 5  // 下面
};

2. 修改loadOpenGLObjects函数,添加EBO的创建与绑定

要在VAO绑定的状态下创建并绑定EBO,这样VAO会自动记录EBO的绑定状态:

// 注意:把m_EBO作为类成员变量,或者确保它的生命周期足够(别在函数内提前销毁)
GLuint m_EBO;

void loadOpenGLObjects() { 
    glGenVertexArrays(1, &m_VAO); 
    glBindVertexArray(m_VAO); 

    // 处理顶点数据VBO(这部分你原来的代码没问题)
    glGenBuffers(1, &m_VBO); 
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 24, vertices, GL_STATIC_DRAW); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); 
    glEnableVertexAttribArray(0); 

    // 新增:创建并绑定EBO,上传索引数据
    glGenBuffers(1, &m_EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 注意:解绑VAO前不要解绑EBO,VAO会保存当前的ELEMENT_ARRAY_BUFFER绑定状态
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 
    // 解绑EBO,此时VAO已经记住了它的绑定,后续绑定VAO时会自动关联EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

3. 修正draw函数的索引数量

把glDrawElements的第二个参数改成索引数组的实际长度36:

void draw() { 
    glBindVertexArray(m_VAO); 
    // 第二个参数是索引的总数量,对应咱们定义的36个索引
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); 
    glBindVertexArray(0); 
}

额外提醒

  • EBO的生命周期要和VAO一致,别提前销毁,不然VAO关联的EBO会变成无效对象。
  • 如果你不想用索引绘制,也可以改用glDrawArrays,直接传顶点数量(比如你的24个是8个顶点,每个3个分量,所以传8),但索引绘制能大幅减少顶点数据的冗余,更推荐用EBO的方式。

内容的提问来源于stack exchange,提问作者magicDM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:27:54