java - 为什么我的 VBO 比显示列表慢?

标签 java opengl lwjgl vertex-buffer displaylist

我创建了两个简单的体素引擎,实际上只是容纳立方体的 block 。对于第一个,我使用显示列表,并且可以毫无问题地以 60 FPS 渲染数百个 block ,尽管其背后的技术已经存在多年且现已弃用。在我的 VBO 版本中,我尝试渲染 27 个 block ,但突然下降到低于 50 FPS。是什么赋予了?我将着色器用于我的 VBO 版本,但不用于显示列表一。如果没有 VBO 版本的着色器,我仍然可以获得相同的 FPS 速率。我将发布一些相关代码:

VBO

block 的初始化:

public void initGL() {
    rand = new Random();

    sizeX = (int) pos.getX() + CHUNKSIZE;
    sizeY = (int) pos.getY() + CHUNKSIZE;
    sizeZ = (int) pos.getZ() + CHUNKSIZE;

    tiles = new byte[sizeX][sizeY][sizeZ];

    vCoords = BufferUtils.createFloatBuffer(CHUNKSIZE * CHUNKSIZE * CHUNKSIZE * (3 * 4 * 6));
    cCoords = BufferUtils.createFloatBuffer(CHUNKSIZE * CHUNKSIZE * CHUNKSIZE * (4 * 4 * 6));

    createChunk();

    verticeCount = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE * (4 * 4 * 6);

    vCoords.flip();
    cCoords.flip();

    vID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vID);
    glBufferData(GL_ARRAY_BUFFER, vCoords, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    cID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, cID);
    glBufferData(GL_ARRAY_BUFFER, cCoords, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
private void createChunk() {
    for (int x = (int) pos.getX(); x < sizeX; x++) {
        for (int y = (int) pos.getY(); y < sizeY; y++) {
            for (int z = (int) pos.getZ(); z < sizeZ; z++) {
                if (rand.nextBoolean() == true) {
                    tiles[x][y][z] = Tile.Grass.getId();
                } else {
                    tiles[x][y][z] = Tile.Void.getId();
                }
                vCoords.put(Shape.createCubeVertices(x, y, z, 1));
                cCoords.put(Shape.getCubeColors(tiles[x][y][z]));
            }
        }
    }
}

然后渲染:

public void render() {
    glBindBuffer(GL_ARRAY_BUFFER, vID);
    glVertexPointer(3, GL_FLOAT, 0, 0L);

    glBindBuffer(GL_ARRAY_BUFFER, cID);
    glColorPointer(4, GL_FLOAT, 0, 0L);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    shader.use();
    glDrawArrays(GL_QUADS, 0, verticeCount);
    shader.release();

    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

我知道我使用四边形,这很糟糕,但我也在我的显示列表引擎中使用四边形。着色器非常简单,它们所做的就是获取颜色并将其应用到顶点,我什至不会发布它们,它们就是这么简单。

显示列表

初始化:

public void init() {
    rand = new Random();

    opaqueID = glGenLists(1);

    tiles = new byte[(int) lPosition.x][(int) lPosition.y][(int) lPosition.z];

    genRandomWorld();
    rebuild();
}
public void rebuild() {
    glNewList(opaqueID, GL_COMPILE);
    glBegin(GL_QUADS);
    for (int x = (int) sPosition.x; x < (int) lPosition.x; x++) {
        for (int y = (int) sPosition.y; y < (int) lPosition.y; y++) {
            for (int z = (int) sPosition.z; z < (int) lPosition.z; z++) {
                if (checkCubeHidden(x, y, z)) {
                    // check if tiles hidden. if not, add vertices to
                    // display list
                    if (type != 0) {
                        Tile.getTile(tiles[x][y][z]).getVertices(x, y, z, 1, spritesheet.getTextureCoordsX(tiles[x][y][z]), spritesheet.getTextureCoordsY(tiles[x][y][z]));
                    } else {
                        Tile.getTile(tiles[x][y][z]).getVertices(x, y, z, 1);
                    }
                }
            }
        }
    }
    glEnd();
    glEndList();
    spritesheet.bind();
}

我应该注意,在我的显示列表版本中,我只添加了可见的立方体。因此,这可能是一个不公平的优势,但它不应该将 VBO 版本降低到只有 27 个 block 的 FPS,而显示列表版本则为 500 个 block 。 我这样渲染:

public void render() {
    if (tiles.length != -1) {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glCallList(opaqueID);
    }
}

所以,在完成所有这些代码之后,我真的仍然想知道为什么我的 VBO 版本这么慢?当我调用它们进行渲染时,我的显示列表版本中确实有一维 block 列表,而我的 VBO 版本中有一个 3 维 block 列表,但我认为 JVM 几乎消除了额外维度带来的任何滞后。那么,我做错了什么?

最佳答案

如果没有实际的项目和分析器,很难回答这样的问题,所以这些都是理论:

  • 您没有详细显示显示列表生成代码,因此我假设您正在执行类似的操作 glColor(); glVertex3f(); 在循环中(不是您声明一次颜色并完成它)。
  • 显示列表实现是特定于实现的,但通常是顶点属性的交错数组,因为这对缓存更友好(所有顶点属性都按 16 字节紧密对齐,而不是按数组大小分散)。另一方面,您使用的 VBO 包含两个非交错的 block - 坐标和颜色。这可能会导致过度不友好的缓存使用(尤其是在处理大量数据时)。

正如评论中所述:

try interleaving your position and colour data in a single buffer. That is the usual recommendation for static data as it gives better memory access patterns during rendering. – GuyRT`

关于java - 为什么我的 VBO 比显示列表慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20231456/

相关文章:

java - JSTL fmt 不工作

c++ - 如何使用 GLEW、OpenGL 或 SDL2 以椭圆运动围绕另一个圆旋转?

java - GL_POLYGONMODE不知道如何正确使用

java - 在 LWJGL 中组织代码

java - 无法解析工件。缺少 : ---------- 1) org. codehaus.mojo :gwt-maven-plugin:jar:1. 3-SNAPSHOT

java - 尝试使用 Spring 应用程序中的实体管理器从数据库中删除记录后出现 NullPointer 异常

java - 为什么实现接口(interface)的抽象类可能会错过接口(interface)方法之一的声明/实现?

c++ - glTexImage2D 使用 4G 内存的 nVidia 视频卡内存不足

java - 如何绘制从相机到 3D 区域的投影线?

OpenGL - 自定义透视矩阵和着色器的问题