Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (553)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Java2D Bloom  (Read 6071 times)
0 Members and 1 Guest are viewing this topic.
Offline StumpyStrust
« Posted 2012-07-24 09:59:33 »

So as you all can probably tell I have been goofing around with java2d alot lately Smiley and here is as close as I can get to having real time bloom in pure java2D.  Grin I used the bloom/glow filter from jhlabs.

http://www.mediafire.com/?1d0q54er1298uu3

and screen



P pauses
space changes particle color.
V for random velocity.
Q and W to change the bloom resolution....sorta

As you can guess, resizing the window greatly effects the performance as it is all software rendering.

I am using the particle system from my particles tutorial.

This is really small and could be use in java4k maybe.  Clueless



Offline jonjava
« Reply #1 - Posted 2012-07-24 10:41:27 »

I like it!

Offline Damocles
« Reply #2 - Posted 2012-07-25 22:08:03 »

The effect looks nice.
But I think there is still room for performance improvements.
It does get choppy on medium resolutions.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline StumpyStrust
« Reply #3 - Posted 2012-07-26 00:04:57 »

I really can't think of any huge performance boosts other then switching to opengl. You have to create a bufferedimage, get its pixels, edit the pixels, and then set them back onto the bufferedimage. It is just slow. The only way to get an reasonable performance is by drawing the image at a lower resolution, filtering it, and then redraw at the original resolution.

If you have any ideas I am all ears.

I am making a game with it now. Should be kinda fun.


Offline Gudradain
« Reply #4 - Posted 2012-07-26 04:27:15 »

Are you creating a bufferdImage everytime you draw?

Just asking because creating a BufferedImage and (even worse) getting the graphics from a BufferedImage is very slow. Compare to that making hundred of calls to methods of Graphics2D is much faster.
Offline StumpyStrust
« Reply #5 - Posted 2012-07-26 07:10:05 »

You can not get the pixels from a graphics object. That is why it is slow. If you could, you could do all sorts of cool effects. I have to create a buffered Image and to draw to and to perform the filter on. But this is sped up a bunch by using a VolatileImage and drawing with its graphics object then using the getSnapShot() method to draw onto a scaled down bufferedImage which is then filtered. I get reasonable performance with this.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
Graphics2D g2d = (Graphics2D) bufferstrat.getDrawGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            v = this.createVolatileImage(render.getWidth(), render.getHeight());
            b = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
                  .getDefaultConfiguration().createCompatibleImage(render.getWidth()/scale, render.getHeight()/scale);
            b.setAccelerationPriority(1);
            v.getGraphics().fillRect(0, 0, v.getWidth(),v.getHeight());        
            renderGame(v.getGraphics());
           
              b.getGraphics().drawImage(v.getSnapshot(),0,0,render.getWidth()/scale,render.getHeight()/scale,null);
              b = bloom.filter(b, b);
             
             
             
              g2d.drawImage(b,0,0,render.getWidth(),render.getHeight(),null);
              for(int j = 0; j <= powers.size() - 1;j++){
               powers.get(j).render(g2d);
            }
            g2d.dispose();


If there was some way of getting pixels in a different way I am more then interested.

Offline Damocles
« Reply #6 - Posted 2012-07-26 08:02:03 »

Check this code out.
I made a little Applet with a similar particle effect
(just some bouncing particles)
Increase the number of particles to see how the speed behaves.
I limited the framespeed, to keep it steady with different amounts of particles.


bloomparticles - Applet



1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
package bat4k;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.Random;

/*
 * Particle Animation, by Damocles
 */

public class BloomParticles extends Applet implements Runnable
{
   //screen dimensions
  static final int WIDE = 1000;
   static final int HIGH = 800;
   //particles
  static final int MAX_PARTICLES = 6000;
   static final int MAX_FRAMES = 50;

   
   public void init()
   {
      new Thread(this).start();
   }

   public void start()
   {
      setSize(WIDE, HIGH);
   }

   public void run()
   {
      try
      {

         while (!isActive()) Thread.yield();

         BufferedImage screen = new BufferedImage(WIDE, HIGH, 1);
         int[]  pixl = ((DataBufferInt) screen.getRaster().getDataBuffer()).getData();
         Graphics g = screen.getGraphics();

         g.setColor(new Color(0x00000000));
         Graphics gCanvas = getGraphics();

         Random ran = new Random();

         //prep particle lightarray
        //x,y,fade-frames
        int[][][] particleFrame = new int[10][10][MAX_FRAMES];

         for (int i = 0; i < MAX_FRAMES; i++)
         {

            for (int x = 0; x < 10; x++)
            {
               for (int y = 0; y < 10; y++)
               {
                  double dist = Math.sqrt((x - 5d) * (x - 5d) + (y - 5d) * (y - 5d));

                  dist = 255 - dist * 60 - i;

                  dist = dist < 0 ? 0 : dist;
                  dist = dist > 255 ? 255 : dist;

                  particleFrame[x][y][i] = (int) dist;
               }
            }
         }

         int[] particlesFrame = new int[MAX_PARTICLES]; //frame
        float[][] particlesBase = new float[MAX_PARTICLES][4]; //x,y , velocity x,y

         for (int i = 0; i < MAX_PARTICLES; i++)
         {
            particlesBase[i][0] = WIDE/2+ ran.nextInt(WIDE/4) - WIDE/8;
            particlesBase[i][1] = HIGH/2+ ran.nextInt(HIGH/4)- HIGH/8;

            particlesBase[i][2] = ran.nextFloat()*2 - 1f;
            particlesBase[i][3] = ran.nextFloat()*2 - 1f;

            particlesFrame[i] = ran.nextInt(MAX_FRAMES);
         }

         long lastFrame = System.nanoTime();

         while (isActive())
         {

            g.fillRect(0, 0, screen.getWidth(), screen.getHeight());

            for (int i = 0; i < MAX_PARTICLES; i++)
            {

               particlesFrame[i]++;
               if (particlesFrame[i] >= MAX_FRAMES) particlesFrame[i] = 0;

               if (particlesBase[i][2] < 0d && particlesBase[i][0] < 10) particlesBase[i][2] = -particlesBase[i][2];
               else if (particlesBase[i][2] > 0d && particlesBase[i][0] > WIDE - 15) particlesBase[i][2] = -particlesBase[i][2];

               if (particlesBase[i][3] < 0d && particlesBase[i][1] < 10) particlesBase[i][3] = -particlesBase[i][3];
               else if (particlesBase[i][3] > 0d && particlesBase[i][1] > HIGH - 15) particlesBase[i][3] = -particlesBase[i][3];

               particlesBase[i][0] += particlesBase[i][2];
               particlesBase[i][1] += particlesBase[i][3];

               int px = (int) particlesBase[i][0];
               int py = (int) particlesBase[i][1];

               for (int x = 0; x < 10; x++)
               {
                  for (int y = 0; y < 10; y++)
                  {

                     int pc = (pixl[WIDE * (y + py) + x + px]) & 0xFF;
                     pc += particleFrame[x][y][particlesFrame[i]];
                     pc = pc > 255 ? 255 : pc;
                     int pc2 = (pc > 230) ? pc : 0;

                     pixl[WIDE * (y + py) + x + px] = pc | (pc << 8) | (pc2 << 16);

                  }
               }
            }

            gCanvas.drawImage(screen, 0, 0, null);

            //limit framespeed
           do
            {
               Thread.yield();
            } while (System.nanoTime() - lastFrame < 0);
            lastFrame += 33 * 100 * 100 * 100;

            //use this without framelimited
           //Thread.yield();
        }

      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }

}

Offline StumpyStrust
« Reply #7 - Posted 2012-07-26 08:39:55 »

Keeps my cpu usage at 25% cant go higher without multithreading. Interesting way of doing things. My effect would be greatly diminished if I did not scale down the size. By scaling down the size, it makes the effect more exaggerated and much faster but you lose quality.

Offline Damocles
« Reply #8 - Posted 2012-07-26 09:43:20 »

Try to never squeeze out all your PCs performance. Its likely that you have a better PC than the average user.
And a game usually gets slower during development.

I try to keep a big enough buffer, and test on a relatively slow System.

Anyway, directly manipulating the pixels  (((DataBufferInt) screen.getRaster().getDataBuffer()).getData()Wink
of the Raster is quite performant.

Very important is to keep the main rendering loop as short and direct as possible.
Dont do calculations there that you can buffer beforehand.
And dont create any Objects! only reference them

Offline nsigma
« Reply #9 - Posted 2012-07-26 10:24:29 »

The JHLabs filters don't offer very good performance for animation.  They go through various hoops to keep the BufferedImage from being unmanaged - which is a pointless exercise when you're updating them every frame.  You should create 2 BufferedImages too, otherwise the filter will create a temporary image and do an unnecessary copy every frame.  You should also probably not use the createCompatibleImage() method for this either, as the filter is converting the data to ARGB.

Your best bet is to create 2 ARGB BufferedImages, grab the data arrays like @Damocles suggests, and fork the filter code so that you can pass in the input and output arrays rather than BufferedImages.  That should speed things up a bit.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jezek2
« Reply #10 - Posted 2012-07-26 12:49:46 »

You can also use optimized algorithm like in this paper: An efficient algorithm for Gaussian blur using finite-state machines
Offline Roquen
« Reply #11 - Posted 2012-07-26 12:59:57 »

NOTE: That optimization and multi-dimensional arrays (in java) are mutually exclusive.
Offline jezek2
« Reply #12 - Posted 2012-07-26 14:21:00 »

NOTE: That optimization and multi-dimensional arrays (in java) are mutually exclusive.

Not true, nobody sane uses multidimensional arrays in Java, you just index it manually in single dimensional array.
Offline Roquen
« Reply #13 - Posted 2012-07-26 14:41:34 »

I don't understand.  You say "not true", then repeat the same thing I said in different words.
Offline nsigma
« Reply #14 - Posted 2012-07-26 14:45:08 »

@Roquen - where did multi-dimensional arrays come from?

@jezek2 - is there a Java implementation of that anywhere?

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Damocles
« Reply #15 - Posted 2012-07-26 14:56:07 »

Maybe he referrs to my example code.
I know that single dimensional arrays are quicker. (around 30% for the pure lookup logic)
But I find that is an optimization that can be done in the end. During coding I see multi-dim arrays as much nicer to read and edit.

Things like making a multi to a single array is just mechanical optimization when cleaning up the program.

the main point of the example was to show how much faster direct pixel manipulation is

Offline jezek2
« Reply #16 - Posted 2012-07-26 15:48:38 »

I don't understand.  You say "not true", then repeat the same thing I said in different words.

Oh sorry, thought you meant the optimization in the paper I posted link to.

@jezek2 - is there a Java implementation of that anywhere?

What kind of dumb question is that? The pseudocode is trivial (and the text describing it is quite simple too), so you shouldn't have any problem translating it to Java...
Offline nsigma
« Reply #17 - Posted 2012-07-26 15:54:09 »

What kind of dumb question is that?

A TL;DR one!  Wink  Have filed away for later perusal.  Still, no matter how simple, it's always useful when someone's already done the work for you!  Grin

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline StumpyStrust
« Reply #18 - Posted 2012-07-26 22:29:29 »

Thank you all for the advice.

When I said 25% cpu I meant that is what your app was running at. I try to keep my stuff running around 5-8% cpu or lower. Currently, this bloom filter runs at 7-15 depending on how many particles there are. I changed the filter so it takes int[] of the pixels and outputs int[], this has sped things up a little I am very impressed. I am still really new to a lot of more complex things when it comes to coding. Here is what I have decided to make after having some fun with this thing.



Its all done without any images and is very small. Kinda break it styled. Very hard to play because there is so much going on. Lots and lots of glowing particles to distract you from the glowing ball.

Offline Damocles
« Reply #19 - Posted 2012-07-27 04:26:47 »

The screen looks really nice.

Offline gimbal

JGO Knight


Medals: 25



« Reply #20 - Posted 2012-08-01 15:03:29 »

The screen looks really nice.

So nice that it is seriously screwing with my eyes. I imagine that is what it looks like when someone that really needs glasses takes them off.

Well done!
Offline matheus23

JGO Kernel


Medals: 106
Projects: 3


You think about my Avatar right now!


« Reply #21 - Posted 2012-08-01 17:06:51 »

I imagine that is what it looks like when someone that really needs glasses takes them off.
Yeah... It seems like your eyes like to do a gaussian-blurr-post-processing-shader instead of giving you a nice picture of what you see...

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline nsigma
« Reply #22 - Posted 2012-08-01 17:11:44 »

Yeah... It seems like your eyes like to do a gaussian-blurr-post-processing-shader instead of giving you a nice picture of what you see...

I've got eyes like that too, and if I stand up too quickly I get this wonderful particle effect too - just think of the power of the GPU in my head!  Wink

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #23 - Posted 2012-08-01 17:21:14 »

nobody sane uses multidimensional arrays in Java, you just index it manually in single dimensional array.
So everyone who's ever done a tutorial or answered a question about making tilemaps is insane?

Do you mean I should do it with a 1D array and treat it as a matrix as described here

instead of this:
1  
2  
3  
4  
5  
6  
int[][] tiles = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};


Huh

- Jonas
Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #24 - Posted 2012-08-01 17:38:15 »

So everyone who's ever done a tutorial or answered a question about making tilemaps is insane?

Do you mean I should do it with a 1D array and treat it as a matrix

I certainly believe not all tutorials uses multi-dimensional arrays, but I get the sentiment. Smiley

There's a ton of tilemap-implementations, and you can do it however you want. Using a single array is just more of a pain to implement versus the time spent. It's not worth it, unless you're looking for a tiny optimization. Mostly, you aren't. The only "real" difference is the lookup time (it's about double in the multidimensional), but it doesn't really make a difference unless you're quering a lot!

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 783
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #25 - Posted 2012-08-01 17:46:24 »

I think those tutorials use that memory layout for the sake of clarity, which is what a tutorial is all about anyway.

Eventually you're going to store your level in a file, and from there on you don't give a crap about what the sourcecode representation would be.

On the other hand, one dimensional or multi-dimensional array lookups (for a tile-engine) are not going to be your bottleneck either way.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #26 - Posted 2012-08-01 17:53:32 »

Thanks for clearing that up. I was afraid I was in for a terribly confusing rewrite of my level-system  Emo

But since you're querying all tiles in the tilemap (within the screen and all that) every update, wouldn't it be a big optimization considering it takes half the time to do each look-up with a 1D array?

- Jonas
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 783
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #27 - Posted 2012-08-01 18:03:15 »

Don't guess, measure.

Multiplying a tiny value by 2, still leaves you with a tiny number.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline matheus23

JGO Kernel


Medals: 106
Projects: 3


You think about my Avatar right now!


« Reply #28 - Posted 2012-08-01 19:37:57 »

Erm... I'm kind of feeling old-school or whatever here...
I've always used two-dimenisonal arrays until I added my N-Dimensional array mapping class?!? (which was just some days ago...)  Huh

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

TehJavaDev (15 views)
2014-08-28 18:26:30

CopyableCougar4 (25 views)
2014-08-22 19:31:30

atombrot (38 views)
2014-08-19 09:29:53

Tekkerue (34 views)
2014-08-16 06:45:27

Tekkerue (32 views)
2014-08-16 06:22:17

Tekkerue (20 views)
2014-08-16 06:20:21

Tekkerue (30 views)
2014-08-16 06:12:11

Rayexar (66 views)
2014-08-11 02:49:23

BurntPizza (43 views)
2014-08-09 21:09:32

BurntPizza (34 views)
2014-08-08 02:01:56
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!