【问题标题】:LWJGL Speed Rendering upLWJGL 加速渲染
【发布时间】:2014-08-21 20:59:37
【问题描述】:

我正在使用 LWJGL 创建一个 Minecraft 克隆。

问题是我只能获得大约 20 FPS。 (每个方向约 32 个街区) 此外,当我更改块时,视图会冻结几毫秒。

我正在使用 Slick 加载纹理。为了渲染块,我将 VBO 用于纹理和顶点(没有 VAO 或着色器或法线)。每个块由 6 个四边形组成,这些四边形由 2 个三角形组成。块之间的面不会被渲染。渲染线程检查所有 32 * 32 块是否已加载到缓冲区以及是否应加载(取决于播放器位置)的每一帧。如果需要它们,则会创建 vbo 并将句柄保存到列表中。如果块太远,缓冲区将被删除。渲染时,当前在显卡内存中的所有 vbo(保存在列表中的句柄)都被绘制。

如何加快渲染速度?我是否应该一直“加载”缓冲区并只绘制所需的对象?法线、VAO 或着色器可以帮助我获得巨大的改进吗?尽管如此,如果我获得更高的帧速率,将会有 mor 块而不仅仅是一个盘子,我打算导入 .obj。

Minecraft 在我认为的 DisplayLists 中呈现。那会是一个解决方案吗?为每个块或块创建一个显示列表并在块或块更改时重新编译它们?

编辑:我用 VisualVM 测量最耗时的方法是 glDrawArrays()。

一些源代码:

渲染:

public static void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    for(VBO vbo : vbos)
    {
        //disable texture smoothing
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glBindTexture(GL_TEXTURE_2D, vbo.texture);
        glBindBuffer(GL_ARRAY_BUFFER, vbo.vertex_handle);
        glVertexPointer(vbo.vertex_size, GL_FLOAT, 0, 0l);
        glBindBuffer(GL_ARRAY_BUFFER, vbo.texture_handle);
        glTexCoordPointer(vbo.texture_size, GL_FLOAT, 0, 0l);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glDrawArrays(GL_TRIANGLES, 0, vbo.vertices);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
}

块加载检测:

int chunkX = (int)(camera.getX() * (-1) / GameData.CHUNK_SIZE);
        int chunkZ = (int)(camera.getZ() * (-1) / GameData.CHUNK_SIZE);

        for(int cx = 0;cx < GameData.NUMBER_OF_CHUNKS;cx++)
        {
            for(int cz = 0;cz < GameData.NUMBER_OF_CHUNKS;cz++)
            {
                boolean shouldBeLoaded = (Math.abs(chunkX - cx) <= 2 && Math.abs(chunkZ - cz) <= 2);

                if(GameData.chunks[cx][cz] != shouldBeLoaded)
                {
                    if(shouldBeLoaded)
                        Util.loadChunk(cx, cz);//loads every block in the chunk
                    else
                        Util.unloadChunk(cx, cz);
                }
            }
        }

块加载:

public void load()
{
    try{
        if(GameData.map[x][y+1][z] == null || GameData.map[x][y+1][z].id == 2)
            top = Util.createQuad(x, y+1, z, 1, id);
    }catch(IndexOutOfBoundsException e){};

    try{
        if(GameData.map[x][y-1][z] == null || GameData.map[x][y-1][z].id == 2)
            bot = Util.createQuad(x, y, z, 1, id);
    }catch(IndexOutOfBoundsException e){};

    try{
        if(GameData.map[x-1][y][z] == null || GameData.map[x-1][y][z].id == 2)
            left = Util.createQuad(x, y, z, 0, id);
    }catch(IndexOutOfBoundsException e){};

    try{
        if(GameData.map[x+1][y][z] == null || GameData.map[x+1][y][z].id == 2)
            right = Util.createQuad(x+1, y, z, 0, id);
    }catch(IndexOutOfBoundsException e){};

    try{
        if(GameData.map[x][y][z-1] == null || GameData.map[x][y][z-1].id == 2)
            front = Util.createQuad(x, y, z, 2, id);
    }catch(IndexOutOfBoundsException e){};

    try{
        if(GameData.map[x][y][z+1] == null || GameData.map[x][y][z+1].id == 2)
            back = Util.createQuad(x, y, z+1, 2, id);
    }catch(IndexOutOfBoundsException e){};
}

Util.createQuad()

public static VBO createQuad(float x, float y, float z, int axis, int id)
{
    boolean xA = axis == 0;
    boolean yA = axis == 1;//senkrecht
    boolean zA = axis == 2;

    FloatBuffer vertex_data = BufferUtils.createFloatBuffer(6 * 3);
    if(xA)
    {
        vertex_data.put(new float[] { x, y, z, });
        vertex_data.put(new float[] { x, y, z+1, });
        vertex_data.put(new float[] { x, y+1, z+1, });

        vertex_data.put(new float[] { x, y, z, });
        vertex_data.put(new float[] { x, y+1, z, });
        vertex_data.put(new float[] { x, y+1, z+1, });
    }
    if(yA)
    {
        vertex_data.put(new float[] { x, y, z, });
        vertex_data.put(new float[] { x, y, z+1, });
        vertex_data.put(new float[] { x+1, y, z+1, });

        vertex_data.put(new float[] { x, y, z, });
        vertex_data.put(new float[] { x+1, y, z, });
        vertex_data.put(new float[] { x+1, y, z+1, });
    }
    if(zA)
    {
        vertex_data.put(new float[] { x, y, z, });
        vertex_data.put(new float[] { x+1, y, z, });
        vertex_data.put(new float[] { x+1, y+1, z, });

        vertex_data.put(new float[] { x, y, z, });
        vertex_data.put(new float[] { x, y+1, z, });
        vertex_data.put(new float[] { x+1, y+1, z, });
    }

    FloatBuffer texture_data = BufferUtils.createFloatBuffer(6 * 2);
    texture_data.put(new float[] { 0f, 0f, });
    texture_data.put(new float[] { 1f, 0f, });
    texture_data.put(new float[] { 1f, 1f, });

    texture_data.put(new float[] { 0f, 0f, });
    texture_data.put(new float[] { 0f, 1f, });
    texture_data.put(new float[] { 1f, 1f, });


    vertex_data.flip();
    texture_data.flip();

    int vbo_vertex_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    int vbo_texture_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_texture_handle);
    glBufferData(GL_ARRAY_BUFFER, texture_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindVertexArray(0);

    VBO vbo = new VBO(vbo_vertex_handle, vbo_texture_handle, renderEngine.textures.get(id), 6, 3, 2);

    if(id == 2)//transparent
        renderEngine.vbos.add(vbo);
    else
        renderEngine.vbos.add(0, vbo);;

    return vbo;
}

【问题讨论】:

    标签: java performance opengl rendering lwjgl


    【解决方案1】:

    我目前正在使用显示列表,因为我还是 lwjgl 的新手,发现 VBO 相当混乱,我所做的只是检查玩家是否移动了 16 个或更多块,或者删除/放置了一个块,这就是我更新我的列表,否则我不会更新列表,您还应该停止渲染您看不到的任何面,因此在检查要绘制哪些面时,您还应该检查它们是否不在您的视图范围内,这是一个示例我愿意;这个例子检查我是否应该渲染某个块的顶面: if(PlayerY

    使用显示列表,对于 48*48 的视图范围,我可以获得大约 200 - 300 FPS,在 128 时,你将获得大约 20 - 100 FPS。 编辑: 如果您还没有使用纹理图集,您还应该开始使用它,这减少了 bind() 调用,这使得它变得更快。

    祝你好运,希望我能帮到你:)

    【讨论】:

      猜你喜欢
      • 2014-01-17
      • 2012-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多