Java 使用LWJGL渲染2D瓷砖的最快方法?

Java 使用LWJGL渲染2D瓷砖的最快方法?,java,opengl,2d,lwjgl,Java,Opengl,2d,Lwjgl,我开始观看使用LWJGL创建2d自上而下游戏的教程,我读到VBO应该很快,但对于每帧渲染48*48个瓷砖,我只能获得大约100FPS的速度,这相当慢,因为我将为游戏添加更多的内容,而不仅仅是一些静态的、不移动或更改的瓷砖 我能做些什么来加快速度?请记住,我刚刚开始学习lwjgl和opengl,所以我可能不会知道很多东西 无论如何,这里是我代码的一些部分(我从代码中删除了一些毫无意义的部分,并用一些描述替换它们): 主回路 double targetFPS = 240.0; dou

我开始观看使用LWJGL创建2d自上而下游戏的教程,我读到VBO应该很快,但对于每帧渲染48*48个瓷砖,我只能获得大约100FPS的速度,这相当慢,因为我将为游戏添加更多的内容,而不仅仅是一些静态的、不移动或更改的瓷砖

我能做些什么来加快速度?请记住,我刚刚开始学习lwjgl和opengl,所以我可能不会知道很多东西

无论如何,这里是我代码的一些部分(我从代码中删除了一些毫无意义的部分,并用一些描述替换它们):

主回路

double targetFPS = 240.0;
        double targetUPS = 60.0;

        long initialTime = System.nanoTime();
        final double timeU = 1000000000 / targetUPS;
        final double timeF = 1000000000 / targetFPS;
        double deltaU = 0, deltaF = 0;
        int frames = 0, updates = 0;
        long timer = System.currentTimeMillis();

        while (!window.shouldClose()) {
            long currentTime = System.nanoTime();
            deltaU += (currentTime - initialTime) / timeU;
            deltaF += (currentTime - initialTime) / timeF;
            initialTime = currentTime;

            if (deltaU >= 1) {
                // --- [ update ] ---
                --INPUT HANDLING FOR BASIC MOVEMENT, CLOSING THE GAME AND TURNING VSYNC ON AND OFF USING A METHOD FROM THE INPUT HANDLER CLASS--

                world.correctCamera(camera, window);

                window.update();

                updates++;
                deltaU--;
            }

            if (deltaF >= 1) {
                // --- [ render ] ---
                glClear(GL_COLOR_BUFFER_BIT);
                world.render(tileRenderer, shader, camera, window);
                window.swapBuffers();

                frames++;
                deltaF--;
            }
            --PRINTING THE FPS AND UPS EVERY SECOND--
        }
使用的输入处理程序方法:

I have this in my constructor:
this.keys = new boolean[GLFW_KEY_LAST];
for(int i = 0; i < GLFW_KEY_LAST; i++)
    keys[i] = false;

And here are the methods: 
public boolean isKeyDown(int key) {
    return glfwGetKey(window, key) == 1;
}
public boolean isKeyPressed(int key) {
    return (isKeyDown(key) && !keys[key]);
}
public void update() {
    for(int i = 32; i < GLFW_KEY_LAST; i++)
        keys[i] = isKeyDown(i);
}
这是模型类中的构造函数和呈现方法:

public Model(float[] vertices, float[] texture_coords, int[] indices) {
    draw_count = indices.length;

    v_id = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, v_id);
    glBufferData(GL_ARRAY_BUFFER, createBuffer(vertices), GL_STATIC_DRAW);

    t_id = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, t_id);
    glBufferData(GL_ARRAY_BUFFER, createBuffer(texture_coords), GL_STATIC_DRAW);

    i_id = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);

    IntBuffer buffer = BufferUtils.createIntBuffer(indices.length);
    buffer.put(indices);
    buffer.flip();

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void render() {
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, v_id);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, t_id);
    glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);
    glDrawElements(GL_TRIANGLES, draw_count, GL_UNSIGNED_INT, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}
我将顶点、纹理坐标和索引存储在平铺渲染器中:

float[] vertices = new float[]{
            -1f, 1f, 0, //top left     0
            1f, 1f, 0, //top right     1
            1f, -1f, 0, //bottom right 2
            -1f, -1f, 0, //bottom left 3
    };

    float[] texture = new float[]{
            0, 0,
            1, 0,
            1, 1,
            0, 1,
    };

    int[] indices = new int[]{
            0, 1, 2,
            2, 3, 0
    };

我不知道还有什么可以放在这里,但是完整的源代码和resources+shader文件可以在github上找到。

对于您当前的系统,我建议您根据纹理对瓷砖进行分组。创建如下内容:

Map tiles=newhashmap()

然后,当您要渲染瓷砖贴图时,只需为每组瓷砖设置一次纹理,而不是为每个瓷砖设置一次纹理。这为将纹理/纹理ID推送到GPU节省了PCI-E带宽。您可以这样实现(伪代码):

沿着这些线我看到的另一件事是,你将投影矩阵分别推送到每个瓷砖上。运行着色器程序时,给定均匀性的值将保持不变,直到您对其进行更改或程序结束。将投影矩阵均匀设置一次


您似乎每调用一次
renderTile(…)
。如果该值不变,请在渲染过程之前计算一次,然后在
renderTile(…)
方法中将其作为变量传入,而不是传入
camera
world

将所有静态分幅捆绑到一个模型中,以便在绘制调用时减少WAAAY(
gldrawerelements()
&co.)关联状态更改(&A)。还要查看纹理地图集和/或阵列纹理。我如何才能做到这一点?(捆绑平铺)在
顶点
/
纹理
/index`数组中没有单个四边形的几何体,而是有整个层的价值。但是,我该怎么做呢?我应该在谷歌搜索答案/教程吗?就像我说的,我是一个彻头彻尾的傻瓜,我不能完全理解我看的教程中的所有内容。那么我可以去掉shader.setUniform()行,在设置投影后开始游戏时只调用它一次吗?如果我这样做了,opengl如何知道将瓷砖放在哪里,因为在第二个集合中,我也传递了包含位置的目标矩阵?我想我误解你了。
public Model(float[] vertices, float[] texture_coords, int[] indices) {
    draw_count = indices.length;

    v_id = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, v_id);
    glBufferData(GL_ARRAY_BUFFER, createBuffer(vertices), GL_STATIC_DRAW);

    t_id = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, t_id);
    glBufferData(GL_ARRAY_BUFFER, createBuffer(texture_coords), GL_STATIC_DRAW);

    i_id = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);

    IntBuffer buffer = BufferUtils.createIntBuffer(indices.length);
    buffer.put(indices);
    buffer.flip();

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void render() {
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, v_id);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, t_id);
    glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);
    glDrawElements(GL_TRIANGLES, draw_count, GL_UNSIGNED_INT, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}
float[] vertices = new float[]{
            -1f, 1f, 0, //top left     0
            1f, 1f, 0, //top right     1
            1f, -1f, 0, //bottom right 2
            -1f, -1f, 0, //bottom left 3
    };

    float[] texture = new float[]{
            0, 0,
            1, 0,
            1, 1,
            0, 1,
    };

    int[] indices = new int[]{
            0, 1, 2,
            2, 3, 0
    };
for (Texture tex : tile.keySet())
{
    BIND TEXTURE
    for (Tile tile : tiles.get(tex))
    {
        SET UNIFORMS
        RENDER
    }
}