代码之家  ›  专栏  ›  技术社区  ›  Teodor Vecerdi

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

  •  1
  • Teodor Vecerdi  · 技术社区  · 8 年前

    these

    我该怎么做才能更快?请记住,我刚刚开始学习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 void render(TileRenderer renderer, Shader shader, Camera camera, Window window) {
        int posX = ((int) camera.getPosition().x + (window.getWidth() / 2)) / (scale * 2);
        int posY = ((int) camera.getPosition().y - (window.getHeight() / 2)) / (scale * 2);
        for (int i = 0; i < view; i++) {
            for (int j = 0; j < view; j++) {
                Tile t = getTile(i - posX, j + posY);
                if (t != null)
                    renderer.renderTile(t, i - posX, -j - posY, shader, world, camera);
            }
        }
    }
    

    这是TilerEnder中的renderFile()方法:

    public void renderTile(Tile tile, int x, int y, Shader shader, Matrix4f world, Camera camera) {
        shader.bind();
        if (tileTextures.containsKey(tile.getTexture()))
            tileTextures.get(tile.getTexture()).bind(0);
    
        Matrix4f tilePosition = new Matrix4f().translate(new Vector3f(x * 2, y * 2, 0));
        Matrix4f target = new Matrix4f();
    
        camera.getProjection().mul(world, target);
        target.mul(tilePosition);
    
        shader.setUniform("sampler", 0);
        shader.setUniform("projection", target);
    
        model.render();
    }
    

    这是模型类中的构造函数和呈现方法:

    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
        };
    

    我不知道还能放些什么,但github上有完整的源代码和资源+着色器文件 here

    1 回复  |  直到 8 年前
        1
  •  1
  •   Nick Clark    8 年前

    Map<Texture, List<Tile>> tiles = new HashMap<Texture, List<Tile>>()

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

    for (Texture tex : tile.keySet())
    {
        BIND TEXTURE
        for (Tile tile : tiles.get(tex))
        {
            SET UNIFORMS
            RENDER
        }
    }
    

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

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

    推荐文章