2D performance problems

Hello

Im having troubles getting decent performance out of a simple 2d tilescroller. Java alphablending with translucent transparency is god awful slow, as expected.
What I want is simple colorkeying, eg defining a transparent color in the source. Couldn’t find any direct way of doing that. Instead I read up on bitmask transparency.

Im loading image data from RGBA png files. So to get them ready for blitting I converted them like this:


            BufferedImage original = ImageIO.read(in);
            java.awt.GraphicsEnvironment ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
            java.awt.GraphicsDevice gd = ge.getDefaultScreenDevice();
            java.awt.GraphicsConfiguration gc = gd.getDefaultConfiguration();
            BufferedImage bim = gc.createCompatibleImage(original.getWidth(), original.getHeight(), Transparency.BITMASK);
            Graphics2D g2d = (Graphics2D) bim.getGraphics();
            g2d.setComposite(AlphaComposite.Src);
            g2d.drawImage(original, 0, 0, null);

To my horror this is for some reason just as slow as Transparency.TRANSLUCENT :frowning:
I tried reading img data from GIF instead in case Transparency.BITMASK only works for indexed colormodel, with no noticeable speed difference.
Besides i’d still like to able to use 24 color instead of 8 bit, and I don’t think thats whats slowing it down either. I get flawless performance on 24 RGB with Transparency.OPAQUE.

What am I doing wrong? seems like java2d is doing per pixel RGBA blitting when I want it to use BITMASK (colorkeying).

oh and is there anyway of using colorkeying specifying your own color key as a 24 bit RGB value? And can I even assume that the above code auto converts RGBA data from the png to
RGB + transparency bitmask?

Try replacing this:
BufferedImage bim = gc.createCompatibleImage(original.getWidth(), original.getHeight(), Transparency.BITMASK);

with this

VolatileImage bim = gc.createCompatibleVolatileImage Image(original.getWidth(), original.getHeight(), Transparency.TRANSLUCENT);

Also, you don’t want to create a new image every frame, do it once, then just draw on top of the image every frame.

When using VolatileImages there are some other checks you need to do when displaying them, just google it.

Hope that helps!
Keith

Thank you for your reply

I’ve read about volatile images, but I thought they didn’t make difference without acceleration, especially under linux where you don’t have the directdraw render path.
I don’t want to rely on hardware acceleration to archieve a playable framerate, then i’d gone opengl from the beginning.
Just thought java2d was fast enough to blit a tilemap with colorkey transparency to a 800x600 window in software. Anyway i’ve begun blitting the first layer of tiles as OPAQUE and the rest
as BITMASK. Helps tremendously.
I still can’t understand why simple on/off colorkey transparency isn’t faster than per pixel alphablending.
An underlying RLE implementation should result in even faster colorkeyed blits than a straight copy.

Don’t insult my intelligence good sir :wink:

What’s the size of the tiles? you using bufferstrategy?

In my game I’m not having any trouble, my bottom tiles are all bitmask then I have a overlay over the whole game window for night which is translucent. I thought I would get slow downs, but I tested in Java 5 and 6 without and slow downs running about 6% cpu 30fps with intel graphics. I guess the game window is smaller, but still…

yes im using bufferstrategy(2). On a canvas inside a JFrame under linux. Framesize is 800x600 and I render 27x20 = 540 32x32 tiles minimum each frame.
I’ve got a simple 3 layer setup: draw layer 1 opaque, 2 bitmask, entities (players and bullet) translucent, layer 3 bitmask. This gives me an acceptable framerate (60-80).
When I first posted this I didn’t render layer 1 opaque but with bitmask (colorkey) transparency.

I know per pixel alpha is very slow in software but colorkeying should be just as fast or faster even (since you don’t have to draw as many pixel as with opaque), thus I cannot understand
why there is such a dramatic difference between OPAQUE and BITMASK… and such a small one between BITMASK and TRANSLUCENT.
I blit my tiles from one sheet image (an opaque for layer 1 and a bitmask’ed for layers 2-3) using drawImage(dst, 8 ints etc) (and im not unintentionally scaling, since rendering all tiles as opaque nets a 166+ FPS)

[quote]yes im using bufferstrategy(2). On a canvas inside a JFrame under linux. Framesize is 800x600 and I render 27x20 = 540 32x32 tiles minimum each frame.
[/quote]
ps: you should really think about CommanderKeith advice, you will have then more free CPU for doing others stuff

if you want performance its recommended you use a java opengl binding, it’ll be much faster than java2d. A good library to try is Slick found at http://slick.cokeandcode.com it has similar api to java2d so porting your game should be pretty quick.

thanks Ill look further into Volatile images. The reason why I was a bit dismissive of the idea was after reading stuff like this:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4498974

Eg. Graphics2D will only be accelerated on linux using the OpenGL pipeline.
I went with java2d on purpose, because I want my game to be playable without a 3d card. I have experience using OpenGL for 2d (and 3d for that matter)
using lwjgl as well as using the native library directly from C.
I don’t want to rely on acceleration but of course I won’t actively hinder it either. Bitmask transparency not being noticeable quicker than translucent transparency just
had me a bit flabbergasted. Guess its because the underlying implementation supports X bit alpha channels and have no optimization for the 1bit alpha channel case.
Figured I might be doing it the wrong way hence this topic.

I apologize if my remark about creating the image every frame came off as arrogant, what I meant was that of course I don’t convert it every frame :slight_smile:

Kapta: I’ve been checking out Slick as well as the rest of Kevin’s site. Great stuff and ill love to try it out for a future project but in this case it was a design goal
to stay with software rendering.

I’m used to doing 2d with libSDL and was expecting bitmask transparency to be as fast as opaque blitting (since there is no technical reason it couldn’t be).

http://geekserver.dk/~bison/s1.png

As of now I’m getting acceptable performance blitting the ground layer opaque and the other layers with bitmask transparency, but as you can see there aren’t
that many transparent tiles in the screenshot.