Painting optimization

My game is running too slow.
When I run a profiler I see that graphics2d.paint() takes most of the cpu time. The size of the game panel is 1024*768.
I am double buffering and using BufferedImages created via GraphicsConfiguration.createCompatibleImage().

The game has several screens which include buttons and animations.
I am using Awt.Containers/Components for the different screens/game elements because its easier then to manage them on screen and also receive mouse clicks on the buttons.

In order to have to program paint only after I update the game I don’t forward the update() call in the double buffered screen to the paint() call but rather call the paint() method myself ( with getGraphics() )after each game update in the main run() loop. ( Active Rendering )

It seems to me like I’m painting a lot. Each screen has an 1024*786 background which I’m painting every iteration in the run() method. I have to paint at least some of that image again and again because I have animations playing in front of it.

I don’t want to use LWGL because I want the program to be multi platform. How much faster will the program run if I do switch to lwgl ?

Will abandoning AWT containers/components increase the game speed? If so is there any library for handling painting in a way that minimizes the number of paint calls/ minimizes the areas repainted?

Any suggestions?
Thanks.

LWJGL works on Windows, Mac and Linux. Unless you’ve got a compelling reason to run on Solaris that should be enough shouldn’t it? ???

For speeding things up, I’d suggest using a BufferStrategy if you’re not already (although if you’re using Swing/AWT components you might have issues with that). I’d also make sure all your images are being created as accelerated/compatable images with only single-bit transparency for maximum drawing speed.

Although 1024x768 is getting a bit big to expect smooth performance out of Java2D IMHO. Once you’ve covered it in tiles you won’t have many sprites left for your objects/etc.

I don’t know how much painting is requered to make game slow, but I also have a 1024x768 game (FSEM), active rendering, and It isn’t slow at all. Profile your paint() method to see what part is actually slow. Maybe you are doing something extra that doesn’t need to be done?

Thanks for the quick replies.
I’ll try profiling the paint method and also try using the BufferStrategy.

Orangy Tang, how much performance increase should I expect from converting to LWGL?

Kova, are you using Awt Containers/components in your game? Are you repainting the whole 1024*768 every update?

Thanks.

The BufferedImage methods are terribly slow, so slow in fact that I was able to render a perspective correct texture mapped scene with full semi-transparency in software quicker than I could update the buffers. This is how I do it:


	void initializeGraphics ( int[] buffer ){
		int w,h;
		w = screenWidth;
		h = screenHeight;
		
		ColorModel colorModel = new DirectColorModel(24, 0xff0000,
				 0x00ff00, 0x0000ff);
		
		SampleModel sampleModel = new SinglePixelPackedSampleModel(
				DataBuffer.TYPE_INT, w, h, new int[] { 0xff0000, 0x00ff00,
						0x0000ff });

		DataBuffer dataBuffer = new DataBufferInt(buffer, w * h);

		WritableRaster raster = Raster.createWritableRaster(sampleModel,
				dataBuffer, new Point(0, 0));
		image = new BufferedImage (colorModel, raster,true, new Hashtable());
	}

	public void update ( Graphics g ) {
		paint(g); // don't want to be clearing the screen, we're drawing the whole thing so just paint
	}
	public void paint ( Graphics g ) {
		if ((g != null) && (image != null)){
			java.awt.Toolkit.getDefaultToolkit().sync();	// sync the display on some systems
			g.drawImage(image, 0, 0, null);
		}
	}


Just call refresh to redraw the component.

I am using BufferStrategy, FSEM, using my custom swing components (need to be custom so you can do active rendering), painting whole 1024x768 image of course (clearing whole screen and repainting).
The game isn’t complicated, for test i draw 11 40x40 images (players+goalie), the goal (284x52), the ball (20x20), few strings for score, time and such, a custom JTextArea, bunch of lines for wireframe and that is about it. Max is ~110 fps. If I add more players fps doesn’t fall at all (which is kind of strange…).
Oh yeah, I remember now… I am using translucent images, and windows don’t accelerate them by default, so I use System.setProperty(“sun.java2d.translaccel”, “true”); … but now if i turn it off no change. Guess JRE 6 “fixed” it.

here’s SS (not from described test above, but older look-what-I-did):

http://img232.imageshack.us/img232/4537/viktorije1en2.th.jpg

EDIT:

this should not be the case, BufferedImages are accelerated most of the time. You are probably changing them and that pushes them to be read from normal RAM.

Actually no; I [at the time] used a single setRGB(int,int,int,int[],int,int) call each frame, which was dead slow, after which I copied to the panel in the paint method. I then moved to the method I showed you now, which gives me great speeds; what method are you using (in regards to drawing to the buffer)? That could be the reason why his method is running slow!

And when you said that you “are using Awt.Containers/Components for the different screens/game elements”, do you mean that you are drawing sprites using them, or just for other methods. Either way you may find that you are drawing all of the screen elements each frame due to [say] having transparent layers and not specifying update regions when you are updating.

Hi, I suggest you to pay attention to the Swing improvements sheet (search by google.com). Well I’ve read it for my own, but it is quite interesting… Besides the previous recommandations about BufferStrategy etc., I would tell you to have a more compatible code structure to send to the Swing Dispatcher Thread which is the BIG common problem.
Hence, I would adjust your paint mathod to fully respect Swing Specs, see, update graphics is the method called -when the Swing Interface needs it- while the component’s graphics are told to be “damaged”. Understand you call repaint() and the Dispatcher will send an update notice to the Swing Interface for this component. Thus update shouldn’t be modified unless you add a super.update() quite for the same reason it is required by Swing to make child and parent updates.
Also useful is the constant cleared graphics that you will receive from the Swing Dispatch’ as it calls paint for each component that has to be updated.
Finally the BufferedImage you use is the most compatible Class but VolatileImage increases speed while it cannot support transparent background. I use Volatile for my offscreen and Buffered for the on-screen components.
And for the refresh thread simply use a component.repaint() to make the drawing.
:smiley:

I have this feeling you may have misread what I was saying; I should have said, "many of the advised methods to use in BufferedImage are terribly slow. When I used them my own software 3d rendering code was rendering quicker than setRGB(int,int,int,int[],int,int) with both RGB and RGBA buffers. I now use a much faster method, this is it:

// blah blah blah

i’d recommend you switch over to Slick http://slick.cokeandcode.com its api is similar to java2d so shouldn’t take long to switch over and it has tons of nice tools and since it uses LWJGL you should get a massive speed boost.

I use containers/components for painting as well. I just call repaint() whenever they are modified.
I thought that would take care of clipping the drawing regions. I think it doesn’t actually matter because I end up ignoring all the paint() calls other than the one in the main loop which calls the paints the top container. This probably results in painting everything again.
If I go with passive rendering I end up getting some flicker in some containers. I presume thats because the paint() thread can’t access all the components all the time.

I’m not sure I understand how keldon85 improved performance. Is it just by initializing the image through the initializeGraphics ( int[] buffer ) call? Does this result in the image being rendered faster every paint() call? Currently I just read pngs to a Java.Image and then paint the image to a BufferedImage to get it accelerated.

`Image loadedImage= Toolkit.getDefaultToolkit().createImage(byte[]);

BufferedImage bufImage=
GraphicsConfiguration.createCompatibleImage(loadedImage.getWidth(null),
loadedImage.getHeight(null),
Transparency.TRANSLUCENT);

bufImage.getGraphics().drawImage(im, 0, 0, null);`

You’d be getting the flicker because you’re updating at the same time that the screen is; for that reason you might want to put in a sync(). That’s pretty much what I would have done with the images. It improved performance for me because I’m rendering a full screen so I’m not copying a preloaded sprite every frame. But really I just wanted to know what exactly you were doing.

Having said that you might want to give that library a try and see if you still get any speed problems.

It sounds like plenty of well-qualified people are chiming with good ideas here.

One extra opinion: avoid ever referencing a DataBuffer, if you can help it. This may affect some platforms (Macs) more than others, though.

This article talks about why:

I’d recommend making a BufferedImage as keldon85 suggests. Or if your code relies on a fixed image type, then you can just use the BufferedImage constructor that takes that fixed image type and call getRaster().setDataElements() to fill in the image data yourself.

Here’s exactly what Toolkit.sync() actually does, because it doesn’t sync the monitor refresh with your frame rate - see this post where it was explained to me: http://www.java-gaming.org/forums/index.php?topic=15000.0

Keith