Acceleration for 2D rendering

Hello, I’m writing a 2D game (surprise). Presently sprites are drawn using fillPolygon. It is necessary to rotate, scale and translate these from an abstract map to the screen, and for this I use AffineTransforms. Also, in order for the polygons to be rendered acceptably I have enabled antialiasing.

The problem is that these simple operations seem to be done in software, and framerate quickly falls below 20 if multiple sprites are visible. I have tried enabling the “opengl pipeline”, but this seems to make no difference. It appears that antialiasing is by far the most demanding aspect of this.

How, then, is it possible to accelerate rendering? It must surely be possible since 3D graphics are so much more complicated and still work quite efficiently.

Tell me if I should post some code.

Well, 2D is not 3D. Antialiasing is extremly expensive and is even with OpenGL enabled done in software.

Where do you render to? To screen, managed image or VolatileImage?

lg Clemens

Thanks for the reply.

Rendering is presently done in a JPanel using paintComponent(Graphics). Swing automatically supplies double buffering, but I do not know exactly how it accomplishes this (i.e. whether it internally uses a Buffered- or VolatileImage). Maybe I should consider using a Canvas (which seems to be a popular way of rendering custom graphics) and then manually specify a BufferStrategy?

By the way, I tested the program with 1.4.2, and this actually further degraded performance significantly! This suggests that the rendering is at least partially accelerated in 1.5.0.

ah, I re-read your post and now its clear:

If antialiasing is used, no accerlation at all will take place, regardless the pipeline you use (exception OGL).
I have seen better performance when using teh OGL on my system (compared to X11), OGL only does some things in HW and some in SW.

The only advice I can give you is to turn AA off and maybe use the rotate-methode of Graphics2D instead of AffineTransform (but not 100% sure about this).

lg Clemens

[quote]rotate-methode of Graphics2D instead of AffineTransform (but not 100% sure about this)
[/quote]
There’s no difference between using G2D.rotate() and G2D.setTransform()…

AA rendering is not accelerated in 1.5, but there were other performance improvements in 1.5 which probably attributed to better performance.

It’s strange that enabling opengl pipeline didn’t help. Are you sure it was being used? Try with -Dsun.java2d.opengl=True (with capital T), it’ll say if it was enabled or not.

There are known performance issues with opengl (mostly because of drivers), though.

Thanks,
Dmitri
Java2D Team

Thank you, and excuse my lateness. My harddrive started making funny noises so I had some backup to do :o

After some brief experiments, the OGL pipeline seems to be solely responsible for the increase in performance in 1.5.0 over 1.4.2 (this is in Linux using an nVidia card). Disabling the pipeline yielded a framerate identical to that of 1.4.2! The lack of performance increase before might be due to some mistake, or maybe because things were different in Windows (directX and whatnot).

I’m still disappointed about the performance though, let’s hope AA will be accelerated some day.

Wait, I’m confused. If you’re using the opengl pipeline, then AA is accelerated.

Dmitri

Sorry, some confusion on my behalf: are rotated/scaled images accelerated by the OpenGL pipeline?

Well, I the OGL-pipeline-bog said that its not “really” accerlated. At least there are a lot of software-loops working in background…

Well, scaled images are accerlated as far as I know, if you scale them at drawing. I don’t know about rotating…

lg Clemens

Oh, AA is accelerated with the pipeline?

Anyway, to clear things up here’s a screenshot:

http://www.student.dtu.dk/~s021864/screen.png

Drawing consists of fillPolygon (each ship hull polygon consists of 26 points, for example), fillOval and drawLine except for the explosions which are images.

The pipeline is used, and the computer is an AMD 1200 MHz with a GeForce 4 MX440. The framerate is capped at 50, but is presently (two ships) only 25. Since an arbitrary unit in Warcraft 3 is more complicated than the entire screen here, it seems reasonable that there should be a more efficient way.

I just reread
http://weblogs.java.net/blog/campbell/archive/2004/11/behind_the_grap.html
which deals with some of these things.

So, er, any ideas? I know this is very vague. By the way, if you look at the screenshot, notice how ugly the “circles” in the radar panel are. When I don’t use the pipeline they look quite nice and circular. Is there a way to fix this?

HopeDagger: the above document states that the following imaging operations are accelerated:

simple copies (e.g. drawImage(img, x, y, null))
simple scales (e.g. drawImage(img, x, y, w, h, null))
arbitrary transforms (e.g. drawImage(img, xform, null))

Why do not blit the ships, this would especially help with the OGL pipeline a lot!

Since you want them to be rendered antialiased this partially explains your bad performance, if you would use pre-drawn ships I think you could tripple your performance. Anyway, turn AA OFF!

Wowow - you completly mix two things. Warcraft is completly 3D, there is a bit difference between doing it in 3D or raping 3D api’s and guarantee that it does look equal.
Another problem is, that your graphic card is quit suboptimal for use with the OGL pipeline, believe me, I’ve the same :wink:

Here my tip of the day:
try to start your program with “-Dsun.java2d.trace=log or = count” and see which operations occur how often.
If there are a lot operations with java2d.loops or SwToSurfaceBlit in it, you’re definitivly doing something wich bothers the OGL pipeline a lot.

Very-fine are TextureToSurface blits and the whole OGL??? commands :wink:

lg Clemens

I have actually tried using images, but decided to use polygons instead “to increase performance”. I thought the polygons would be faster since all the pixels have the same colour.

Images, however, do introduce some problems. When I use the pipeline in Linux, interpolation of the rotated images is messed up along the image boundaries. To be exact, white pixels appear along the boundary (they are probably interpolated from “outside” the image which is, per default, white)! This problem appears while using Nearest Neighbor as well as Bilinear interpolation, but not while using Bicubic (bicubic is, however, out of the question because of complexity among other things).

One solution would be to disable the pipeline, since bilinear interpolation seems rather efficient without.

Still, another drawback of images is that the movement appears very jaggy since images are centered on pixels, whereas corners of polygons with AA are simply drawn “between” pixels. (EDIT: solved easily by applying floats in an AffineTransform!)

I will try logging the OGL output as you suggested soon.

Arbitrary transforms are accelerated with the opengl pipeline.

Anyway, check out Chris’ article about the pipeline:
http://today.java.net/cs/user/print/a/147

And the followup about the Singl Thread Rendering:
http://weblogs.java.net/blog/campbell/archive/2005/03/strcrazy_improv_1.html

Thanks,
Dmitri

I have now rendered the polygons and ovals that make up a ship onto a BufferedImage using antialiasing such that it looks nice around the ship edges, and the images are rendered onto screen with bilinear interpolation. This vastly increases performance, while everything looks just as nice as before! I have tested the performance with around 40 ships on the screen, and saw framerates in excess of 40, which is good since it is capped at 50.

It is interesting that antialiasing is so slow while bilinear interpolation is so fast.

As stated before there is a problem with the edges of the images while using linux. This is probably due to bad drivers, but we’ll have to see about that.

Thanks a lot to LinuxHippy for the suggestions, and to Dmitri for the info on the pipeline.

I believe the problem with the sprite edges is fixed in the latest mustang build (b33).

Dmitri

Hi Hjorth_Larsen,

I’ve had great results by just dumping the AWT/Swing framework and using OGL directly via JOGL. It can do anything, and it’s so much faster, it’s not even in the same race.

https://jogl.dev.java.net/

Regards,

  • Vincent

[b] I believe the problem with the sprite edges is fixed in the latest mustang build (b33).

Dmitri [/b]

I installed Mustang b33, but it does not fix the problem. I can supply screenshots and some hardware info if anyone is really interested, but presently I just disable the pipeline by default and rely on the increased performance from bilinear interpolation.

Thanks, Vincent, for the suggestion. In the near future I will stay with Swing, but in the long run I may take a deeper look at JOGL.

Ask

You can fix the sprite edge color bleeding by going over every pixel and set the color of the transparent pixels to the average of it’s opaque neighbours.

Since I’ve been using OpenGL alot, I don’t consider the edge bleed a bug. It’s just how it works.

[quote]You can fix the sprite edge color bleeding by going over every pixel and set the color of the transparent pixels to the average of it’s opaque neighbours.
[/quote]
Yikes, that sounded very scary. None of the transparent pixels in question even have opaque neighbours, except of course the background of the screen on which the images are rendered - but it’s impossible to keep track of that, what with the numerous transformations and such. I took care to have only opaque pixels near the Image boundaries, such that the bilinear interpolation could work correctly.

Are you quite sure that we are talking about the same problem? I did some searching for “color bleeding” but didn’t find anything that looked like my problem. Maybe I should stress that the problem is on the image boundaries, not on the edges between opaque and transparent pixels.

Thanks for the tip though.

Ask

My mistake. I was thinking of another “bug” that has been fixed in mustang. Where the color of transparent pixels bleed over when using bilinear.

Your probably seeing some lack edge clamping. Don’t know of any workaround for that though :frowning: