Slick2D - setFilter() on "blank" Image

Hey,

in my current game I create a minimap like this


   public void init(GameContainer gameContainer, Map map) throws SlickException {
        this.map = map;
        miniMap = new Image(map.getMapWidth(), map.getMapHeight());
        mapGraphics = miniMap.getGraphics();

        for (int y = 0; y < miniMap.getHeight(); y++) {
            for (int x = 0; x < miniMap.getWidth(); x++) {
                if (map.getTileAt(x, y) == 0) {
                    mapGraphics.setColor(Color.green);

                } else if (map.getTileAt(x, y) == 66) {
                    mapGraphics.setColor(Color.blue);
                }
                else {
                    mapGraphics.setColor(Color.white);
                }
                mapGraphics.drawRect(x, y, 1, 1);
            }
        }
        mapGraphics.flush();
    }

and this is the rendering code


   public void render(GameContainer gameContainer, Graphics graphics) throws SlickException {
        int posX = gameContainer.getWidth() - (int)mapScale*miniMap.getWidth();
        miniMap.draw(posX, 0, mapScale);

   
    }

Works ok, but it uses the default GL_LINEAER filter for scaling. Now I need this to use GL_NEAREST as filter, but when I


miniMap.setFilter(Image.FILTER_NEAREST);

before the draw call, slick crashes with

java.lang.RuntimeException: Resource not found: org.newdawn.slick.Image@5dd6b6fa
at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:169)

I guess it’s because there is no resource-texture availabe and it’s a slick-limitation. Is there a known workaround maybe? :smiley:

This is most likely because you are using an old and outdated version of Slick. There have been some changes to setFilter to make it work a bit better.

You can download the new version here:
http://www.slick2d.org/ (Downloads -> Library Only)

Then you will also need to download the latest LWJGL version:
http://lwjgl.org/download.php

For more info on what this is about, see here.

Alternatively, if for some reason you don’t want to use the latest version, here is some ugly code that ought to work:

try {
    //load empty texture with NEAREST filter
    Texture tex = InternalTextureLoader.get().getTexture(new EmptyImageData(width, height), GL11.GL_NEAREST);
    //create a new image using empty texture
    image = new Image(tex);
} catch (IOException e) {
    //texture could not be created... do something
    e.printStackTrace();
}

Well, updating Slick fixed it -.-

Don’t know why I was using an old version, thank you very much!

It’s worth mentioning: What you are doing right now is very slow.

Say your minimap is 32x32 pixels, and you want to update it every frame – that would mean you’d be issuing 1,024 extra draw calls per frame.

You can read up on startUse/drawEmbedded/endUse, which will reduce draw calls. (i.e. Grab a 1x1 opaque white sub-image of your sprite sheet, then you simply bind a color before calling drawEmbedded.)

Alternatively, instead of pushing geometry for each pixel in your minimap, you might have better performance by actually transferring data to a texture. You can check out the PixelData utility that was conceived for this purpose.

... start of render() ...
    //place your colours in the array
    for (...)
        use pixelData.setPixel(..) or pixelData.put(..)
    //transfer the array to the texture on the GPU
    pixelData.apply(minimapImage.getTexture());

I’m confused. The Minimap get’s initialized once and filled with the corresponding pixels.

The only rendering draw call is


int posX = gameContainer.getWidth() - (int)mapScale*miniMap.getWidth();
        miniMap.setFilter(Image.FILTER_NEAREST);
        miniMap.draw(posX, 0, mapScale);

The only update that occurs is the player position on the minimap, which is a red dot currently. I only draw that pixel on top of the current graphics context, not the minimap itself, that way I do not need to reinitialize the minimap.

Thanks for the links, but the game runs at >1k fps. So I don’t think performance is a problem, yet. Might come in handy later tho :slight_smile:

drawRect will push a quad to the GPU. So you’d be pushing 1,024 quads individually (glBegin/glEnd) for a 32x32 minimap.

Again, this is mainly a concern if you plan on updating your minimap per frame. :wink:

There is another small issue; images using getGraphics should use the static method [icode]Image.createOffscreenImage(width, height)[/icode] for initialization, rather than the Image constructor. This is because of a long-standing problem with Slick. The image constructor will still work, but it will lead to an extra texture being created in VRAM – probably not a big deal for your game, but something to keep in mind.

(Maybe you are starting to see how buggy Slick is? :P)

I don’t know what you m- (must use libgdx for next project) ;D ;D