Java LWJGL OpenGL 异常访问冲突 0xc0000005

Java LWJGL OpenGL Exception Access Violation 0xc0000005

调用 glDrawElements() 时出现错误,我无法弄清楚原因:/ 我是 OpenGL 的新手,我正在尝试了解它的工作原理。

注意:我正在使用这个库将 OBJ 文件转换为 OpenGL 应该能够使用的数组:https://github.com/korre/java-obj-to-opengl/blob/master/MeshObjectLoader.java

public class Mesh {

    private int vaoId;

    private List<Integer> vboIdList = new ArrayList<>();

    @Getter
    @Setter
    private float scale = 1;

    @Getter
    @Setter
    private Vector3f position = new Vector3f(0, 0, 0);

    @Getter
    @Setter
    private Vector3f rotation = new Vector3f(0, 0, 0);

    @Getter
    @Setter
    private String textureKey;

    private int vertexCount;

    private Mesh(MeshObjectLoader.MeshArrays meshArrays) {
        vaoId = glGenVertexArrays();
        glBindVertexArray(vaoId);

        var vboId = 0;
        vertexCount = meshArrays.getNumVertices();

        // Load vertices
        vboId = glGenBuffers();
        vboIdList.add(vboId);
        var vertexBuffer = (FloatBuffer) meshArrays.getVertices();
        glBindBuffer(GL_ARRAY_BUFFER, vboId);
        glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0 ,0);

        // Load texture coordinates
        vboId = glGenBuffers();
        vboIdList.add(vboId);
        var textureCoordsBuffer = (FloatBuffer) meshArrays.getTexCoords();
        glBindBuffer(GL_ARRAY_BUFFER, vboId);
        glBufferData(GL_ARRAY_BUFFER, textureCoordsBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

        // Clean everything up
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    }

    public static Mesh loadFromObjFile(String resourcePath) throws IOException {
        try (var resourceStream = Mesh.class.getResourceAsStream(resourcePath)) {
            return new Mesh(MeshObjectLoader.loadModelMeshFromStream(resourceStream));
        }
    }

    public void render(int textureId) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, textureId);

        glBindVertexArray(vaoId);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        glEnable(GL_DEPTH_TEST);
        glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);

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

    public void cleanup() {
        glDisableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        for (int vboId : vboIdList) {
            glDeleteBuffers(vboId);
        }

        glBindVertexArray(0);
        glDeleteVertexArrays(vaoId);
    }

}

崩溃的原因是您从未将缓冲区对象绑定到 VAO 的 GL_ELEMENT_ARRAY_BUFFER 绑定点,因此 glDrawElements(..., 0) 的最后一个参数被解释为 host-address指针而不是任何元素数组缓冲区中的 byte-offset。 当然,取消引用 0 地址会失败。

无论何时调用索引绘图调用,如 glDrawElements,您还需要一个元素数组缓冲区(也称为“索引缓冲区”)。

库 returns 位置、纹理坐标和法线的列表,您只需通过 glDrawArrays() 进行 non-indexed 绘图调用。这也是非常典型的 Wavefront OBJ 加载器,因为 Wavefront OBJ 格式有位置、法线和纹理坐标的单独索引,所以典型的加载无论如何都会对所有面部索引进行 cross-product,并为您提供 linear/duplicated顶点数据列表。

所以:改为 glDrawArrays