Lets just sum this up and make things easy. If you want any form of performance in java2D, you can never grab the pixel array of a bufferedImage every frame.

If you want to do some sort of lighting, then there are other ways of doing it that are much fast. (look at the Toxic Bunny dev blog for details) If you want to do post processing effects, move to opengl. The best I go with a basic bloom filter was really hacky and very slow.

Lets just sum this up and make things easy. If you want any form of performance in java2D, you can never grab the pixel array of a bufferedImage every frame.

If you were attempting to sum up what I was saying, you got it opposite!

Every time you modify a BufferedImage it happens in software. One of the fastest and most flexible ways to modify a BufferedImage is to grab the pixel array. Grabbing it every frame has no performance penalty over other methods of modifying it, and can often be faster! A pity the PulpCore project is discontinued, because this was a good example of pure software rendering in Java, and how direct array manipulation was often faster than the Java2D software pipeline (search Bubblemark on here!).

What I was saying is that if you want to grab the array of an image (sprite) and change it, then draw it lots of times unchanged, you should draw it into another BufferedImage so it can be re-managed.

Now, I do understand that if I'm meddling with the internal structure, it is being handled by the CPU.

From what you've explained, I'm guessing the usual way to draw graphics is to keep the graphic elements in VRAM (say, sprites and backgrounds) and composite (copy into frame) from said copies.

I also understand that certain operations (rotation, scaling, shearing...) need to be supported by the GPU or else the images will be dumped back into Software mode.

Now, as far as sprites, tiles or GUI is concerned, that seems easy to handle.

What I am somewhat concerned is with full-screen effects.

One example is the static filter I'm using for testing, other would be screen glows, or using masks to apply lighting effects...

On one hand I've read that blitting of alpha-enabled images isn't always supported by the GPU, so creating masks as BufferdImages and then applying them might not be a good way to do it.

On the other had, some effects might need per-pixel control (Static being an example, although I can think of a few ways to simulate static with a set of pre-calculated alpha masks).

So how would you suggest these are handled? (And AWT not being able to do these things reliably is a valid answer)

For the record, I'm inquiring now because I'm building the rendering pipeline as I learn, better to decide now on this than backtrack later.

Also, I've noticed slowdowns when experimenting with large resolutions. My target game resolution is around 320x200, so the CPU will probably be able to handle it. This VolatileImage discussion is mostly educational for me.

Scaling has very little performance penalty if any. Rotating will drop performance but will be fine as long as you are not rotating 500-1000 sprites every frame. I think just about all gpu from the last 5 years should support the rotation, scaling, and shearing.

Lets just sum this up and make things easy. If you want any form of performance in java2D, you can never grab the pixel array of a bufferedImage every frame.

If you were attempting to sum up what I was saying, you got it opposite!

I meant modifying the pixels. You can grab them and be ok but if you want to edit them and do something then you are SOL unless there are some tricks that I do not know of.

The idea of drawing to another bufferImage/volatileimage is good if you only do it on start up or maybe one time when a level is loaded. Doing it every frame will kill performance. I used this technique for my bloom filter and it gave a nice speed boost but not enough to get higher then 35fps.

What do you mean by blitting? Are you talking about alpha blending? Then again, you should be fine. Most gpu and even integrated chips support alpha blending. So you should not need any form of mask.

I am not sure what you mean by fullscreen effects. What is the static filter? Adding what looks like static to the game? like an old TV. Screen glow would be bloom? Lighting?

Java2D can draw images very well. You can simulate a lot of cool effects with just drawing an image and using clipping such as lighting.

I would suggest a low resolution (which you have) and making it so the target fps is 24-30 fps. You might be able to manage doing some of these things at that low of a frame rate. If you really want to do all of this in java2D look at Toxic Bunny dev blog. They show what they did to get all of the effects they have. (lighting being the big one)

I doubt this can really be accelerated, unless the code can somehow be run on the GPU.

On the other hand, maybe this effect or rudimentary lighting can be achieved by rendering the light mask into a low resolution image (say at half resolution) and then attempt to have the GPU blit the image into the main frame, combining alpha values.

Oskuro, that is what I thought you meant but there really is no major performance gain from blitting vs just drawing. If there is some, it is not the major bottle neck. The pixel manipulation is your bottle neck.

One idea for the static effect is to have 3-4 images that have bits of static in them and the rest transparent and composite them randomly on the screen. This will give you a similar effect and be very very fast.

You can do the glow effect by rendering a white semi transparent square over the whole window.

Java2D does not do additive blending and if you want to do that then you will have to un-accelerate your drawing surface.

Most effects you will have to fake because java2D was not designed to do them. The lighting being draw onto a smaller map is what I did with some things and it can greatly improve performance. If you use bi linear filtering you can go to 1/3 the resolution and still get fairly good looking lights.

Using a volatile image as a FBO or Texture (not quite sure which one is more accurate) is great and I am not sure if you know about the getSnapShot() method that will give you a bufferedImage of the volatile. This is useful as you can then edit it the pixels you just drew and render them on to your main drawing surface. Think of light maps.

If you really want to do all sorts of cool post processing effects, java2D is not the way to go. At this point with how well you understand everything, you should have no problem getting into opengl or libgdx. I do not know how much you have put into this but it sounds like you want to get going with shaders. (something I am strangling myself with)

Lets just sum this up and make things easy. If you want any form of performance in java2D, you can never grab the pixel array of a bufferedImage every frame.

If you were attempting to sum up what I was saying, you got it opposite!

I meant modifying the pixels. You can grab them and be ok but if you want to edit them ...

So did I! Kind of getting the feeling we're speaking different languages here?!

Directly updating / editing the pixel array of a BufferedImage every frame is actually pretty fast, and it's possible to do this faster (a lot in some cases) than the software Java2D pipeline. If you do this, you should just ignore everything about managed images because they never will or can be managed.

Personally, I'd ignore Java2D as much as possible for anything requiring consistent framerates, performance, etc. It's great for UI's, but it's too unpredictable for many uses, and favours accuracy over performance too much.

If you want consistent(ish) hardware rendering, use libGDX or similar. If you want to work with software rendering and pixel operations in Java, just grab the pixel array of a BufferedImage, play with it, and draw it to a BufferStrategy every frame. It's a usable solution for low / medium resolution stuff as long as you don't go overboard, and performance is far more predictable.

The idea of drawing to another bufferImage/volatileimage is good if you only do it on start up or maybe one time when a level is loaded. Doing it every frame will kill performance. I used this technique for my bloom filter and it gave a nice speed boost but not enough to get higher then 35fps.

Doing it every frame is precisely what I said not to do (at least if you're only drawing it once)! You're just needlessly copying an entire pixel array in Java before it gets streamed to the graphics card. It is potentially worth doing if you need to transform the image when you draw it, but only if you use a VolatileImage.

Blitting is the composition of several bitmaps by means of a raster operation (As defined by wikipedia).

If you're going to stick with the software rendering route, and are just doing plain blitting (no scaling), I'd also recommend looking at this thread - lots of fast blend modes (Add, Multiply, Difference, etc.) for combining the pixel arrays from BufferedImages (or similar). The code derives from Praxis' software pipeline, but was extended and developed further by Dx4 (he also changed to work with single source pixels, which I disagree with). Using these is faster than using drawImage() on a BufferedImage.

I doubt this can really be accelerated, unless the code can somehow be run on the GPU.

Well, one day we'll see Java code running on the GPU - http://openjdk.java.net/projects/sumatra/. In fact, it's doable now with Aparapi. But seriously, if you want to get it running on the GPU, it's time to dive into GLSL.

As I've said, I'm mostly learning the basics of graphics rendering. The use of Java is merely incidental, as I often strip out parts of the standard java classes I have no interest in using. My point is to try and develop a graphics pipeline that would work equally well (with minor library changes) if I were to port the code to other language, or to a different Java implementation, hence the interest in manipulating data buffers as directly as possible.

My main concern is what strategies to use when approaching rendering of different elements. From this thread I gather the following:

When dealing with concrete resources (Sprites, backgrounds, etc) it is best to load them as BufferedImages and compose them together without modification, so the system accelerates them if possible

When dealing with direct manipulation, minimize by reducing resolution or framerate, and whenever an effect is going to remain static for a while (say, the glow around the player when holding a lamp, which will always be the same for as long as the player has that specific lamp) it is best to render it into a texture to be handled as a concrete resource.

I will eventually move into better rendering solutions, right now I just want to try doing things by hand to wrap my mind around how things work under the hood, so to speak.

Also, my first project is meant to be retro-limited, as in low resolution, lack of fancy effect and the like.

Possible follow-up projects I may develop to run on my Blackberry (with no OpenGL support), so it is important I learn to handle things as low level as possible.

In any case, thanks for all the information! It is hard enough to find out information on the net that doesn't directly tell you to use this or that library, so these threads are gold to me!

Word of advice to anyone wanting to meddle with the internal buffer on a BufferedImage:

1 2 3 4 5

//This works (for <type> being int, byte or short, and <Type> being Int, Byte or Ushort)<type>[] bufferData = ((java.awt.image.DataBuffer<Type>)BufferedImage.getRaster().getDataBuffer()).getData();

//This, on the other hand, does not (The BufferImage.getData() method creates a copy of the buffer, that is not backed up by the actual image.<type>[] bufferData = ((java.awt.image.DataBuffer<Type>)BufferedImage.getData().getDataBuffer()).getData();

Yes, I spent all day today wondering why my filters where not working.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org