Best way to render with java2D

so lately ive been working on a few projects with the use of lwjgl, but have ran into some problems with people being able to run my projects(just 2 reported cases)
i cannot be sure that the problem is not with my code but i ran all my programs on about 12 computers and it was worked on 10… so yeah i dont think it is an issue with the client.

Anyway i figured since one of these 2 computers is of a very good friend and its crucial that he help me test my program that i would put in a fall back to Java2d of my program . ive gone and abstracted all my graphics calls and rendering mechanisms but ive come to a dilemma.

In looking for the best ways to render with java2d i found a plethora of methods but not all seem viable. a lot of people suggest i do per pixel rendering onto a buffered image and then g.draw that image because(and this is their logic) making calls to g.drawImage has a lot of overhead.

so what you do with this pixel method is make a new image and draw straight into the raster using a pixel[] array. We do this by looking through each pixel and blah blah blah you get it.

contrary to what i read online, this method was very very slow.

running uncapped rendering one image onto the screen using this method my fps dropped to around 400 fps as opposed to 2300fps when using the g,drawImage.

so currently i am sticking with g.drawImage to draw every single object since its way faster than looping through 40k pixels each frame.

Now my question is . is there some way to optimize rendering images with Java2D? from personal experience or prior knowledge what can you guys come up with?

Thanks in advance :slight_smile:

Well not that I can think of off the top of my head, but there's always culling (not rendering objects when you can't see them or, in 2D, not rendering objects when they are off the screen). An easy way to do culling is to make a Rectangle object the size of the screen and move it with your screen. So basically you have a Rectangle surrounding the screen. Then have a Rectangle around live objects and check every few frames or so if it's colliding with the view Rectangle. If so, g.drawImage(). However this probably is not performant at all it really just popped into my head...

The way I did simple culling when I first started was, if the camera doesn't move, and let's say the screen is 100x100, I checked if the x and y were within -20 and 120 and if so, render.

The rectangle method is perfectly valid! I would check which version of OpenGL your friend has, maybe he doesn’t have a version that supports some of your functions. While its unlikely, it may be the issue. You should try debugging the LWJGL application to see what the problem is, though.

Personally when I am using Java2d I am using this “tricks”:

  1. Creating images compatible with the current graphics environment:
    public static BufferedImage loadImage(String source, int transparency) {
        BufferedImage image;
        try {
            image = ImageIO.read(GraphicsUtils.class.getResource(source));
            GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
            BufferedImage finalImage = config.createCompatibleImage(image.getWidth(), image.getHeight(), transparency);
            finalImage.setData(image.getData());
            return finalImage;
        } catch (IOException ex) {
            Logger.getLogger(GraphicsUtils.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
  1. Scene culling (mentioned before)

  2. Rendering static scene elements to BufferedImage and then rendering this BufferedImage

@opiop65 we have tried that and several other things to no avail. it is why i have instead chosen to refactor my engine so that i may continue coding the game instead of trying to fix his problems . in the future if we do fix it , the engine will be more than able to use lwjgl.

@Mac70 I am currently using a similar method of loading my images. Although i do not quite know how much i am getting out of it by creating compatible images. i have tested with various image types and they all seem to give the same performance.

I’m not 100% certain on how Java2d works (others on here are far more knowledgeable on it), but doesn’t it make use of hardware acceleration behind the scenes if it can? Although I’ve got a sneaking suspicion because your image is constantly changing (i.e. you are manipulating it yourself), it is not a candidate for being accelerated; could this possibly be the reason for the performance drop?

As for trying to squeeze a bit more performance out using your current method, perhaps you could consider using ‘dirty regions’; instead of re-drawing the whole image every update, just update the parts of the image that have changed. Obviously this wouldn’t be much benefit if your image is constantly changing, such as with scrolling backgrounds etc., but if a large portion of the image remains fairly constant you may reduce the number of pixels that you need to loop through and set. You could implement dirty-regions fairly easily with rectangles.

The fastest way to draw an image in java2D is the g.drawImage. There is nothing faster that I know of. The key here is how java2D does this which you cannot control which is why j2d is crap. Also, I believe that all BufferedImage are converted to the most compatible format automatically when they are loaded with ImageIO. Also, all BI are accelerated by default.

Tips: NEVER draw to a bufferedimage. If you want a back buffer to draw stuff to and then composite over the scene use a VolatileImage. Drawing to a BI de-accelerates it. IE slow.

More Tips: Big performance hit with j2d is draw calls. The more g.drawstuff you do the slower it gets. most computers even on integrated chips can get 5-10k draw calls at 60 fps. If you can bring down the draws by drawing a larger image do it.

Last Tip more of guide: Java2D acts very oddly on different computers especially when they have an integrated gpu as their drivers suck. This is really the biggest issue with jd2. The unpredictable performance.

Also, use what mac70 said.

Well, that’s interesting that Java2D actually is faster with its built in functions, I always assumed that it would be faster directly manipulating the pixels. Oh well, the first few months of my coding career were a lie!

yeah man when i started out a while back people swore by it. In the end i ended up just using lwjgl because why not haha . I was going to have to sooner or later. This backwards compatibility is only due to (like i said) one of my main testers not being able to run my game hehe.

and i dont think its an issue with his openGL, he gets an unsatisfied link error which doesnt seem to happen on any other comp other than his.

back on topic though… i can get away with actively rendering 1000 400x200 images that have been made compatible at around 60 constant fps.
i have atholn2 4 core 3.0GHZ and an ati 5800 HD series with 2.5gb VRAM .

if i try any more than the 1000 i get a serious fps drop.
mind you this is without culling or checking for dirty regions because i just want to see how much i can render at once.

Well, why stress it then? Your engine seems more than fine! If you have more than 1000 images visible on the screen at one time, you’re doing something very wrong anyway. I would say just go with it, don’t worry too much about the performance seeing as its only ever going to be used by one person!

yeah i understand , my goal was just to make my software run well on all devices (even if for some reason they cannot get lwjgl to work) with as little graphical discrepancies as possible hehe . Thanks for all the great responses everyone :slight_smile:

You are probably hitting a fill rate limit then. If you get an unsatisfied link exception that means that it cannot load the lwjgl dll/so/sol I think. Look at what OS he as and heck for errors that could cause that and what region the OS is in. Some European countries use a comma as a delimiter for fraction numbers ( ,456) while in the US we use a period. ( .456 ) This can crash a program parsing a file excepting one or the other. Look into it. I could go on about all the woes I have had with my laptop and its shitty optimus software and the weird crap that happens in Java2D when doing some fancy stuff with VolatileImages (real time lighting) but that would take for ever. Thing is, I still tried fixing it, which I did.

Alos, if someones computer does not support at least opengl 2.0, then they do not deserve to play your game. 8)

My school computers literally don’t even have OpenGL support. I think that they somehow removed the drivers for it… Actually, that’s not true because I could still work with it in software rendering.

What kind of a game are you trying to run?

Java can also improve its speed by making the canvas/frame where you are drawing a fixed size. If you can get away making your game on an 800x600 surface, then you can pull even more speed out of it.

The other way to get a good amount of speed is to control the amount of draw calls to the system. (This way, you don’t have to clear the background buffer every frame, but only when an image changes). This increases the speed of Java2D a lot depending on the nature of the game.

Of course, it just depends on the game you are trying to make. The above methods work wonders, but if you really need some more speed, then you’ll have to logically pull it out.

the game will be rendered in different resolutions with the possibility of full screen mode Other than that the screen will not be resizeable. Can you elaborate on how to control the amount of draw calls? and what this “nature” would consist of

Easy hack for doing fullscreen and controlling resolutions. Render everything to a Volatile image at the internal resolution you want. (small drop in performance) then render the VA to the jframe/canvas at the right aspect ratio of the internal resolution and scale based on how large the jframe/canvas is. For full screen, set the frame to undecorated and its size to the size of the native resolution.

internal is 800x600 let the jframe/canvas be native resolution and just scale the internal VA as much as you can and still have it fit inside the jframe/canvas. Make sure to center it and you my have to take mouse inputs and convert them into the internal resolution but that is trivial.

Look at my Retro project to see what I mean.

Here are the 2 files that control much of the core rendering other then g.drawImage stuff

http://pastebin.java-gaming.org/78230686e72
http://pastebin.java-gaming.org/823087e6275

oh thats a nifty little way of doing it. im actually using the graphics device getfullscreenwindow method to invoke a true fullscreen , for the java2d version of the game anyway