绘图时 VAO 和 VBO 崩溃

Posted

技术标签:

【中文标题】绘图时 VAO 和 VBO 崩溃【英文标题】:VAO and VBO Crashing when drawing 【发布时间】:2014-09-18 19:46:13 【问题描述】:

我将代码从 DisplayLists 更改为 VBOs / VAOs。 但是当我运行应用程序时它崩溃了。

第一次尝试绘制 VAO 时它会崩溃。我不使用着色器进行绘制(因此不会引起问题)。

在一个 VAO 中最多有 12 个面(12 * 3 个顶点)以及这些面的纹理坐标。有多达 500 000 个 VAO。

我如何创建一张脸:

tData.add(new float[]textureX + 0.1249f, textureY+ 0.1249f);
vData.add(new float[]x, y, z);
tData.add(new float[]textureX+ 0.1249f, textureY+0.0001f);
vData.add(new float[]x, y+1, z+1);
tData.add(new float[]textureX+0.0001f, textureY+0.0001f);
vData.add(new float[]x+1, y+1, z+1);

创建 VBO/VAO:

if(vData.isEmpty())
        return;

    int vaoHandle = glGenVertexArrays();
    glBindVertexArray(vaoHandle);

    int vertexDataSize = vData.size() * 3;
    int textureDataSize = tData.size() * 2;
    FloatBuffer vertexData = BufferUtils.createFloatBuffer(vData.size() * 3);
    FloatBuffer textureData = BufferUtils.createFloatBuffer(tData.size() * 2);

    while(!vData.isEmpty())
    
        vertexData.put(vData.remove(0));
    
    while(!tData.isEmpty())
    
        textureData.put(tData.remove(0));
    

    vertexData.flip();
    textureData.flip();

    int vertexHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vertexHandle);
    glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
    glVertexAttribPointer(0, vertexDataSize, GL_FLOAT, false, 0, 0);

    int textureHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, textureHandle);
    glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
    glVertexAttribPointer(1, textureDataSize, GL_FLOAT, false, 0, 0);


    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    renderEngine.vaos.add(new VAO(vaoHandle, (int)((float)vertexDataSize / 3f)));

渲染 VBO / VAO:

    glUseProgram(0);//TODO:REMOVE
    for(VAO vao : vaos)
    
        glBindVertexArray(vao.getHandle());
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        System.out.println(vao.getVertices());//correct numeber
        glDrawArrays(GL_TRIANGLES, 0, vao.getVertices());//<-- CRASH at first time called

        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(0);
    
    glBindVertexArray(0);

这是错误:

# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000000b3fb610, pid=7736, tid=6224
#
# JRE version: Java(TM) SE Runtime Environment (8.0_20-b26) (build 1.8.0_20-b26)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.20-b23 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [ig75icd64.dll+0x8b610]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\Geosearchef\workspaces\workspaceLWJGL\OrangeJuiceVBO\hs_err_pid7736.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

我认为在这里发布整个错误是没有意义的。 你知道为什么会这样吗?我找不到有关 VBO 的此错误的任何信息。

【问题讨论】:

你确定你了解VAO是什么以及如何使用它吗?为什么你的程序在绘制的时候是unbound的?还有为什么你在渲染的时候enable.disable attrib arrays?你一定不能在使用 VAO。您在设置 VAO 时启用一次。请阅读如何使用 VAO。 好的,谢谢!不知道这一点,因为它在渲染之前显示:lwjgl.org/wiki/index.php?title=The_Quad_with_DrawArrays,但我认为这是因为它只渲染了一次。我在绘制时解开了我的程序,以确保不是我的着色器(glsl 版本 130,显示列表的原因)导致了问题。我会重写它并在 VBO 工作时启用它。 看这个教程:swiftless.com/tutorials/opengl4/4-opengl-4-vao.html 在渲染期间启用/禁用属性会使 VAO 的使用毫无意义。在设置 VAO 或更改其缓冲区附件时仅执行一次该步骤。在绘图期间只需绑定/取消绑定它。 【参考方案1】:

你没有正确设置顶点属性指针:

int vertexDataSize = vData.size() * 3;
int textureDataSize = tData.size() * 2;
[...]
glVertexAttribPointer(0, vertexDataSize, GL_FLOAT, false, 0, 0);
[...]
glVertexAttribPointer(1, textureDataSize, GL_FLOAT, false, 0, 0);

size参数定义了每个顶点的向量中的元素个数,必须在1到4的范围内。

您的代码只会产生一个 GL 错误 - 您应该明确添加一些错误检查,至少对于调试而言 - 并保持属性指针未初始化。

这里的另一个问题:您使用通用顶点属性 0 和 1,但您不使用着色器。那是行不通的。规范只保证属性索引 0 将映射到经典的 glVertex 属性,但属性 1 可能是任何东西,或者根本不起作用。

【讨论】:

他在代码中做错了很多事情。他在绘图代码中对VAO的使用是完全错误的。 绘制代码严格意义上没有错。只是效率低下。 我更改了 VBO 创建,为每个三角形创建一个 VBO,现在它可以工作了。谢谢你的帮助!与 DisplayList 相比,我仍然不明白使用 VBO 应该更好。我还有 3 FPS(显示列表:70)。这是我对 VBO 的第二次尝试,结果相同。我是在做那么无能的事情吗? @Geosearchef:你的方法完全没有效率。每帧有 500000 个绘制调用也不会很快。只有当您之前有 500000 个显示列表时,您与显示列表的比较才会公平。 每个三角形 使用 2 个独立的 VBO 永远不会去任何地方。您似乎误解了 VBO 的工作原理。 @derhass 现在我有 256 个包含相同数量多边形的 VBO,但仍然获得 3 FPS。

以上是关于绘图时 VAO 和 VBO 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

顶点着色器 VAO 是不是需要 VBO?

不使用 VBO 时 OpenGL 应用程序崩溃

为不同的 VBO 使用 OpenGL VAO

如何在 Qt 5 中使用带有实例化的 VAO

大小太大时 VBO + glBufferData 崩溃

配置VAO和VBO时,顶点数据数组是不是应该使用相同的方法? (OpenGL)[重复]