【问题标题】:OpenGL crashes when trying to use glDrawArraysInstanced()尝试使用 glDrawArraysInstanced() 时 OpenGL 崩溃
【发布时间】:2016-08-10 23:48:52
【问题描述】:

加载到 VAO 函数

glGenVertexArrays(1, &VAO);
glGenBuffers(1, &modelVertexVBO);
glGenBuffers(1, &sphereTransformVBO);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, modelVertexVBO);

glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (sphereModel->numVertices * 3), &(sphereModel->vertices[0]), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);


glBindBuffer(GL_ARRAY_BUFFER, sphereTransformVBO);

glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (maxSphereStorage * 4 * 4), NULL, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4 * 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), NULL);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribDivisor(sphereTransformVBO, 1);

glBindVertexArray(0);

几何绘图功能:

glBindVertexArray(VAO);
glDrawArraysInstanced(sphereModel->mode, 0, sphereModel->numVertices, sphereCount);

当我尝试运行此代码时,它会崩溃并显示以下崩溃说明: 在 Engine.exe 中的 0x0000000068F4EDB4 (nvoglv64.dll) 处引发异常:0xC0000005:访问冲突读取位置 0x0000000000000000。

当我删除第二个 VBO 时,由于某种原因它可以工作。

【问题讨论】:

    标签: c++ opengl crash nvidia vbo


    【解决方案1】:
     glVertexAttribPointer(0, 4 * 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), NULL);
    

    您的崩溃是一个简单的复制粘贴错误的结果。你这里使用了属性 0,也就是说你从来没有为属性 1 调用过glVertexAttribPointer。因此,它使用了默认的属性状态,从而导致了崩溃。

    但是,我强烈怀疑您正在尝试将 4x4 矩阵作为单个属性传递。那是行不通的;如果您尝试将属性的大小设置为大于 4,OpenGL 将give you a GL_INVALID_VALUE error

    Matrices are treated as arrays of (column) vectors。并且每个向量占用一个单独的属性索引。所以如果你想传递一个矩阵,你将不得不使用 4 个属性索引(从你的着色器提供的那个开始)。而且每个人都必须为其设置除数。

    【讨论】:

    • 第一个 bug 其实并不是 bug,粘贴到网站时我不小心把 1 改成了 0。这样你就不会觉得我很蠢 XD
    • glVertexAttribPointer() 中不正确的size 会导致Access violation reading 错误吗?
    • 我不知道,我正在检查它是否重要。
    • @Harish:“glVertexAttribPointer() 中的大小不正确会导致访问冲突读取错误吗?”不是直接的。在大多数 OpenGL 错误的情况下,不会更改任何状态。所以就好像它根本没有被称为它一样。这意味着这是同一个问题,只是方法不同。
    • 我认为glDrawArraysInstanced() 会导致错误,因为它试图读取超出他的第二个缓冲区。
    【解决方案2】:

    为什么要将顶点属性指针重新映射到第二个 vbo?

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
    ...
    glVertexAttribPointer(0, 4 * 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), NULL);
    

    有关glVertexAttribPointer()的更多信息,请参考https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml

    我猜你的抽奖电话

    glDrawArraysInstanced(sphereModel->mode, 0, sphereModel->numVertices, sphereCount);
    

    注意这两种情况下的“0”索引

    超出了您的第二个 VBO 的大小,因此出现错误。您是否有意将顶点属性指针重新映射到第二个 VBO?这会覆盖第一个映射,换句话说,您的第一个 VBO 没有被使用。

    我建议使用GLuint attribute1; 来存储索引并相应地映射以避免将来出现此类问题。像0 这样直接使用数字作为属性索引是犯这种错误的简单方法。

    【讨论】:

    • 粘贴到网站时不小心弄错了,把1改成了0。
    猜你喜欢
    • 2015-12-11
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2012-05-13
    相关资源
    最近更新 更多