简体   繁体   中英

Bad SpriteBatch performance when rendering tilemap [LibGDX]

So I'm rendering a tilemap (simply a twodimensional array with MapTiles), called WorldGeneration, using a isometric renderer class I've created. The camera I'm using uses 64 pixels per meter, so its height for example is: (game window height)/64. The SpriteBatch used in the isometric renderer has it's projection matrix set to this camera. (batch.setProjectionMatrix(cam.combined)

The problem is, I'm getting horrible performance when rendering textures onto this SpriteBatch. I'm not sure if it's caused by the projection matrix being what it is (needing to scale my 64x64 textures to 1x1 in batch dimensions), or something else.

I've tried running the program without executing the batch.draw call in the renderer (see code below) and everything works fine. Is anyone able to find the problem or give me some tips?

Relevant code snippets:

Render method of the isometric renderer:

public void render(WorldGeneration gen) {
    //TODO compensate for elevation
    int x1 = (int) (cameraIso.x - 23); // TODO compensate for zoom
    int x2 = (int) (cameraIso.x + 23);
    int y1 = (int) (cameraIso.y - 23);
    int y2 = (int) (cameraIso.y + 23);

    if(x1 < 0){
        x1 = 0;
    }else if(x1 >= gen.getLengthX()){
        x1 = gen.getLengthX() - 1;
    }

    if(y1 < 0){
        y1 = 0;
    }else if(y1 >= gen.getLengthY()){
        y1 = gen.getLengthY() - 1;
    }

    if(x2 < 0){
        x2 = 0;
    }else if(x2 >= gen.getLengthX()){
        x2 = gen.getLengthX() - 1;
    }

    if(y2 < 0){
        y2 = 0;
    }else if(y2 >= gen.getLengthY()){
        y2 = gen.getLengthY() - 1;
    }

    batch.begin();
    for (int x = x2; x >= x1; x--) {
        for (int y = y2; y >= y1; y--) {
            tiles = gen.getTiles(x, y);
            if(tiles == null){
                continue;
            }else if(tiles.size <= 0){
                continue;
            }
            for(MapTile tile: tiles){
                if(tile.getOpacity() < 1){
                    batch.setColor(batchColor.r, batchColor.g, batchColor.b, tile.getOpacity());
                }else{
                    batch.setColor(batchColor.r, batchColor.g, batchColor.b, 1);
                }
                //TODO only visible (not underneath several tiles)
                pos.x = x;
                pos.y = y;

                //As you can see the texture is scaled to 1x1 because of batch:
                batch.draw(textures[tile.getId()], translateCartToIso(pos).x,
                        translateCartToIso(pos).y + tile.getZ(), 1f, 1f);

            }
        }
    }
    batch.end();
}

As you can see I've even created the Vector2 pos outside the render method to increase performance, but I'm not sure if that's even necessary. It is also worth noting that tiles are locked to a xy grid, but their z value is not, that is why an array is needed.

Edit: Somehow the performance is great if the camera is zoomed out, have no idea why this is. It definitely has something to do with the camera dimensions.

Found the answer, it actually had to do with the graphics behind everything. I noticed that when I ran stress tests my computer (mac) would shut down because of a graphics problem.

It basically came down to this line: cfg.useHDPI = true;

Where I made my LwjglApplicationConfiguration use HD pixels, I guess my computer couldn't handle it when it had to process too many HD pixels (that's why it worked when i zoomed the camera out, less pixels)

I guess I'll have to deal with some distorted pixels for now, that's a problem I'll have to solve later!

I'm not exactly positive on everything your code is doing, but it looks like the outermost loop has a runtime of O(56), the inner for loop has another O(56) runtime, and then the innermost foreach loop has a runtime of O(<# of elements in tiles>) giving you a grand total of: around 3,000 draw calls, assuming one element in tiles.

That's already quite a bit of drawing, not to mention the performance decrease scaling can often impart. Is there no way to optimize that?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM