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

时间:2013-11-27 01:44:12

标签: java opengl lwjgl vertex-buffer displaylist

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

VBO

块的初始化:

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个块的FPS而不是显示列表版本的500个块。 我这样渲染:

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

所以,在完成所有代码后,我仍然想知道为什么我的VBO版本只是如此慢?我在显示列表版本中有一个一维的列表列表,当我调用它们进行渲染时,以及我的VBO版本中的三维块,但我认为JVM几乎消除了额外维度的任何延迟。那么,我做错了什么?

1 个答案:

答案 0 :(得分:0)

如果没有实际项目和手头的探查器,很难回答这个问题,所以这些都是理论:

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

如评论中所述:

  

尝试在单个缓冲区中交错位置和颜色数据。这是静态数据的通常建议,因为它在渲染期间提供了更好的内存访问模式。 - GuyRT`