0

I am making a Java2D game, and I'm trying to alpha-blend layers of the same image to create something similar to blur.

Using AlphaComposite is really slow, and it's dropping the average framerate from 170 to 90, this might not look like a problem (since most games run at 60), but sometimes the framerate drops to lower than 45 (maybe because I'm using a bit more of my computer? not sure), and it seems like a lot for a single effect I'm trying to apply.

In my constructor, I have

AlphaComposite blurAlpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);

AlphaComposite opaque = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1);

then in the main loop: (to be clear, g is the Graphics2D object, and game is the pre-rendered image of the game)

g.setComposite(blurAlpha);
g.drawImage(game, -1, 0, null);
g.drawImage(game, 1, 0, null);
g.setComposite(opaque);

At first I thought the framerate drop was due to drawing the image twice, but when I remove the setComposite lines, the framerate goes up to 150.

Locked
  • 51
  • 8
  • Render it to a `BuffereImage` first, only when you need it, then simply paint the `BufferedImage` – MadProgrammer Apr 22 '19 at 00:48
  • @MadProgrammer I already am, **"[...] and game is the pre-rendered image of the game [...]"**. I am trying to find a way to either a: change the alpha value of the image itself, or b: find a quicker alternative. – Locked Apr 22 '19 at 01:25
  • And how many times do you perform this operation? Every cycle or just when you need to? Do you break it down, so those elements that aren't changing (or don't change often) are buffered? Simply stating "per-rendered" doesn't provide the kind of information which would be helpful, you should consider providing a [mcve] – MadProgrammer Apr 22 '19 at 01:26
  • Then you state "then in the main loop"* you're using the alpha composite, which is the point I'm suggesting should be pre-buffered – MadProgrammer Apr 22 '19 at 01:30
  • Well, I am trying to "blur" the hole screen, so I need to do it every cycle (or at least every time something in the screen moves) – Locked Apr 22 '19 at 01:30
  • Sorry, but I really don't get your point. Even if I pre-buffer the AlphaComposite, I have to run it whenever the player or something in the screen moves... – Locked Apr 22 '19 at 01:32
  • Ok, in my experience, burring is expensive. A [mcve] would help – MadProgrammer Apr 22 '19 at 01:33
  • (I'm not gonna get the code, because it's pretty disperse among other stuff, but you can have an idea of what I'm doing) Ok, so What I do is: - If something in the level is moving, I create a BufferedImage, get its Graphics and draw all the pieces of the level to it. - After the drawing is done, I run the piece of code I already shared Since it is the whole screen, I have to run it every cycle, which is why I moved the AlphaComposite object creation to the constructor of the main class – Locked Apr 22 '19 at 01:38
  • I would like to create a MCV example, but it's not really going to help, as I would need start another project, and tbh, starting the JFrame stuff is the worst part for me when I'm working on a project. – Locked Apr 22 '19 at 01:48
  • Looking at [Java 2D Graphics, The Composite Interface and Transparency](https://www.developer.com/net/vb/article.php/626361/Java-2D-Graphics-The-Composite-Interface-and-Transparency.htm), in the section *"What is the AlphaComposite Class?"*, it suggests that you might get better performance with a "premultiplied" image (using a type of `BufferedImage.TYPE_INT_ARGB_PRE`) ... this is all theory and "reading" as I've not personally tested in your case, but have used `premultiplied` images in the past for performance reasons – MadProgrammer Apr 22 '19 at 01:53
  • Thanks, but I can't seem to find any examples of it online, and since your answer was quite vague, I don't know what do modify in my current code It really doesn't help that the examples on java2s (which is the only source I could clear many of my previous doubts) has giant examples – Locked Apr 22 '19 at 01:59
  • `game` is a what? `Image`? I'm assuming a `BufferedImage`? How is it created, what "type" are you using? You need to considering using `BufferedImage.TYPE_INT_ARGB_PRE` instead, but since I have zero context, this is as much help as I can provide you – MadProgrammer Apr 22 '19 at 02:10
  • ```game``` is a BufferedImage, initialized as follows: ```game = gfxConfig.createCompatibleImage(screenWidth, screenHeight);``` and gfxConfig is a GraphicsConfiguration object – Locked Apr 22 '19 at 02:17
  • That's a good way to do it, which is what I'd normally use, have you considering using `game = new BufferedImage(screenWidth, screenHeight, BufferedImage.TYPE_INT_ARGB_PRE)` – MadProgrammer Apr 22 '19 at 02:19
  • I just did, and not much changed. The framerate is still ~90 with it and ~150 without. – Locked Apr 22 '19 at 02:24
  • I did a really quick test, simply drawing a static image using your `AlphaComposite`, as fast as the program could and I was getting around 850fps with and without the `setComposite` call – MadProgrammer Apr 22 '19 at 04:01
  • Really? I think the problem is the overlapping then. Did you try drawing 2 images on top of each other? – Locked Apr 22 '19 at 04:08
  • I used a single image, painted twice, using your `AlphaComposites` just as you demonstrated. The only difference was I was using `ImageIO.read` directly. I used `createCompatibleImage` and didn't have any difference – MadProgrammer Apr 22 '19 at 04:11
  • wow, to be honest I have no idea what is going on then. At least in theory my case shouldn't be different... – Locked Apr 22 '19 at 04:24

0 Answers0