Slick Forums

Discuss the Slick 2D Library
It is currently Sun Apr 20, 2014 4:52 pm

All times are UTC




Post new topic Reply to topic  [ 46 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Fri Sep 21, 2012 7:12 pm 
Offline

Joined: Sat Feb 19, 2011 2:59 pm
Posts: 52
In GIMP I switched to a sine-curve progression now to draw the light sprites. And in my code (see above) I scaled the lights with factor 8. Together with the stone textures from the image you posted I come to the following result (running at 800 frames per second with 20 moving lights!). With 1000 lights it is still running with over 70 FPS (!).

(Check against http://slick.cokeandcode.com/wiki/doku. ... alpha_maps )

Cons:
- I think the lights here don't look as realistic as the ones in the documentation
- You need to prepare all light colors and brightness levels in your graphics program (i.e. GIMP)

Pros:
- Damn fast!
- Usage of offscreen images possible (but only offscreen-to-screen; offscreen-to-offscreen isn't possible; probably due to a SLICK bug)

Attachment:
lighttest_smallfly.jpg
lighttest_smallfly.jpg [ 161.87 KiB | Viewed 2053 times ]


And since I think this code could help some people which - like me - think the lighting is good enough. Here is the technique: (detailed code see above)

Code:
public void render(GameContainer gc, Graphics g)
{
int ambientLightLevel = 100; // 0 = black as the darkest night; 255 = as bright as day

// offscreen drawing

gOffscreenGame.clear();      
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColorMask(true, true, true, true);
// draw game elements
gOffscreenGame.flush()

gOffscreenLights.clear();
gOffscreenLights.setColor(new Color(255, 255, 255, ambientLightLevel));
gOffscreenLights.fillRect(0, 0, WIDTH, HEIGHT);
gOffscreenLights.setDrawMode(Graphics.MODE_ADD);
GL11.glColorMask(true, true, true, true);
// draw lights (white sprites on transparent background; tip: use sinosodial gradients;
// use slight white for places where a light color will be drawn above and strong white for lights that will be white in the end)
gOffscreenLights.flush();

gOffscreenLightColors.clear();
gOffscreenLightColors.setDrawMode(Graphics.MODE_NORMAL);
GL11.glColorMask(true, true, true, true);
// draw the light colors (colored sprites on transparent background; same size and shape as white lights)
// draw them exactly above slight white colored light sprites
gOffscreenLightColors.flush();

// on screen drawing

g.clear();

g.setDrawMode(Graphics.MODE_NORMAL);
g.drawImage(offscreenGame, 0, 0);
      
GL11.glBlendFunc(GL11.GL_ZERO, GL11.GL_SRC_ALPHA);
g.drawImage(offscreenLights, 0, 0); // here we draw the lights by using the light offscreen image as alpha map
      
g.setDrawMode(Graphics.MODE_ADD);
g.drawImage(offscreenLightColors, 0, 0); // here we add the light colors to the lights
   
g.setDrawMode(Graphics.MODE_NORMAL);
g.flush();
}

_________________
http://www.p1sim.org - Economy/Logistics simulaton based on Java and Slick2D


Top
 Profile  
 
PostPosted: Sat Sep 22, 2012 1:56 pm 
Offline
Oldbie

Joined: Thu Mar 15, 2012 12:38 am
Posts: 270
Looks really good. I think there would be some slight differences given the example lights are much larger than what you have (not sure but was the first thing that popped in my mind when I did the comparisons).


Top
 Profile  
 
PostPosted: Sat Sep 22, 2012 2:00 pm 
Offline

Joined: Sat Feb 19, 2011 2:59 pm
Posts: 52
dayrinni wrote:
Looks really good. I think there would be some slight differences given the example lights are much larger than what you have (not sure but was the first thing that popped in my mind when I did the comparisons).

The documentation solution might look better. But if you need more than a few single lights, you cannot use the docu solution anymore, since the FPS would decrease dramatically.

_________________
http://www.p1sim.org - Economy/Logistics simulaton based on Java and Slick2D


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 1:38 pm 
Offline
Regular
User avatar

Joined: Mon Feb 07, 2011 8:48 pm
Posts: 182
Location: United Kingdom
Yeah after all your research I think I am going to try and run with your solution, thanks for putting all of this time and effort in :)

_________________
Mirage Realms - A free, retro, 2D MMORPG being developed using Slick2D and TWL


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 1:40 pm 
Offline
Oldbie

Joined: Thu Mar 15, 2012 12:38 am
Posts: 270
Maybe we can get this thread added to the Sticky topic: "Code Samples, Tutorials and Help"?


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 1:41 pm 
Offline
Regular
User avatar

Joined: Mon Feb 07, 2011 8:48 pm
Posts: 182
Location: United Kingdom
dayrinni wrote:
Maybe we can get this thread added to the Sticky topic: "Code Samples, Tutorials and Help"?


I was actually thinking it would be great to put the code for smallfly's replication of the documented light tutorial using this new method up on the Wiki as an example.

_________________
Mirage Realms - A free, retro, 2D MMORPG being developed using Slick2D and TWL


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 3:05 pm 
Offline

Joined: Sat Feb 19, 2011 2:59 pm
Posts: 52
Liam wrote:
dayrinni wrote:
Maybe we can get this thread added to the Sticky topic: "Code Samples, Tutorials and Help"?


I was actually thinking it would be great to put the code for smallfly's replication of the documented light tutorial using this new method up on the Wiki as an example.

Do whatever you like with the code. I got help and so I offer help to the community.

_________________
http://www.p1sim.org - Economy/Logistics simulaton based on Java and Slick2D


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 7:57 pm 
Offline
Oldbie

Joined: Thu Mar 15, 2012 12:38 am
Posts: 270
Liam wrote:
dayrinni wrote:
Maybe we can get this thread added to the Sticky topic: "Code Samples, Tutorials and Help"?


I was actually thinking it would be great to put the code for smallfly's replication of the documented light tutorial using this new method up on the Wiki as an example.


Yes! This would be great as well. 8)


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 8:40 pm 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1482
Thanks for the code smallfry. Some considerations:

1. Offscreen images are usually pretty big (padded to power of two, so resolution 1920x1080 -> 2048x2048). To be safe, you should make sure the driver can support such large images with Image.getMaxSingleImageSize() and InternalTextureLoader.get2Fold().

2. Clearing offscreen images is not always the fastest operation; neither is flushing them. Furthermore, each new offscreen image you introduce in the render loop creates more texture thrashing. Ideally we should try to minimize the number of offscreen images we are using. Most of the time, you don't need to use offscreen images, and often it's faster just to render to the screen. I'm not sure why you are using them to render your map and entities.

3. Drawing the same sprites over top each other multiple times creates a lot of unnecessary "overdraw" which can lead to a fill-rate bottleneck. This will be especially apparent if you are using many large and semi-transparent sprites at a high resolution. It's dependent on the GPU -- some have higher fill-rate than others.

With that in mind I've built on your example, reducing the number of offscreen images and doing the light/color mask in a single pass. I'll re-do the wiki to include this example, since it is more efficient and more flexible.

http://pastebin.com/SChc3gq8

The sprite sheet used: (right click + save as)
http://i.imgur.com/04lm9.png

Let me know if this new version has any issues.


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 10:29 pm 
Offline
Regular
User avatar

Joined: Mon Feb 07, 2011 8:48 pm
Posts: 182
Location: United Kingdom
All runs fine here davedes, great job I'll be using your example in my project, thank you very muchly (to all involved) :)

_________________
Mirage Realms - A free, retro, 2D MMORPG being developed using Slick2D and TWL


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 10:56 pm 
Offline

Joined: Sat Feb 19, 2011 2:59 pm
Posts: 52
well done davedes

_________________
http://www.p1sim.org - Economy/Logistics simulaton based on Java and Slick2D


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 11:01 pm 
Offline

Joined: Sat Feb 19, 2011 2:59 pm
Posts: 52
davedes wrote:
Most of the time, you don't need to use offscreen images, and often it's faster just to render to the screen. I'm not sure why you are using them to render your map and entities.

My game does redraw the terrain only when scrolling across the map or zooming. Otherwise only the vehicles (and their lights) are moving. The GUI's windows and panels are also drawn only when moved/resized. The windows' content (buttons etc.) are redrawn very often. Since different layers need to be updated with different frequencies, I need offscreen images. As simple as that.

davedes wrote:
Drawing the same sprites over top each other multiple times creates a lot of unnecessary "overdraw" which can lead to a fill-rate bottleneck.

I will go on with the "normal" development of my project. And in the end I may improve the performance (if necessary). At the moment, Im just happy that the lights work fine and the frames per second are high :)

_________________
http://www.p1sim.org - Economy/Logistics simulaton based on Java and Slick2D


Top
 Profile  
 
PostPosted: Sun Sep 23, 2012 11:51 pm 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1482
Quote:
My game does redraw the terrain only when scrolling across the map or zooming. Otherwise only the vehicles (and their lights) are moving. The GUI's windows and panels are also drawn only when moved/resized. The windows' content (buttons etc.) are redrawn very often. Since different layers need to be updated with different frequencies, I need offscreen images. As simple as that.

This doesn't explain why you need multiple offscreen images. Unlike in Java2D, where "caching" to offscreen images might improve performance, the rule of thumb in Slick/OpenGL:

More offscreen images => more state changes and calls to glBindTexture + glBegin/glEnd => worse performance.

If your terrain tiles and player tiles are packed into the same sprite sheet and you use drawEmbedded where possible, you will probably be able to achieve faster performance than using many offscreen images. You could take it a step further and pack your GUI elements into the same texture atlas (assuming you are targeting 2048x2048, you have a fair bit of space).

You can pack images together programatically (on the fly) if you want to keep the resource files separate.

Look at it this way:

  • Application A uses a single sprite sheet for all of its images. You bind the texture once (at initialization), then use a single glBegin/glEnd pair to render everything.
      glBindTexture per frame = 0
      glBegin/glEnd per frame = 1
  • Application B uses one sprite sheet for tiles, and one for entities. After binding and rendering the tiles, we need to bind and render the entities.
      glBindTexture per frame = 2
      glBegin/glEnd per frame = 2
  • Application C uses one sprite sheet for tiles, and one for entities, and it "caches" the tile map to an offscreen image. First, we need to switch the graphics context to the offscreen buffer (not free). Then we bind and render the tiles. Then we switch back to the screen buffer. Then we need to bind and render the offscreen image. Then we need to bind and render the entities. Let's assume the player is moving the screen and the map needs to be redrawn:
      glBindTexture per frame = 3
      glBegin/glEnd per frame = 3
      state changes per frame = 2

Since Slick games are rarely vertex-bound, using offscreen images as a means of "caching" a few hundred quads is generally not worth it.

I talk a little more about offscreen images here:
viewtopic.php?p=31187#p31187


Top
 Profile  
 
PostPosted: Mon Sep 24, 2012 10:39 am 
Offline

Joined: Sat Feb 19, 2011 2:59 pm
Posts: 52
davedes wrote:
If your terrain tiles and player tiles are packed into the same sprite sheet and you use drawEmbedded where possible, you will probably be able to achieve faster performance than using many offscreen images. You could take it a step further and pack your GUI elements into the same texture atlas (assuming you are targeting 2048x2048, you have a fair bit of space).


Thanks for your detailed answer (here and in the linked thread). Now I got a better understanding of how the OpenGl rendering works.

To be honest: I didn't care how many sprite sheets I used. I am currently using about 5 and in the end - when the game is finished - there will be about 50 sprite sets, since I am using 1024x1024 images to store my sprites and the sprites of a city/economy/traffic simulation need much space.

Till now I didn't use the begin/embedded/end stuff. I just draw the single sprites to the screen. The terrain sprites are spreaded over 4 sprite sheets and thus there are hundreds (or thousands) of texture.bind() calls when my terrain gets rerendered. Currently to the offscreen. When the offscreen gets drawn to the screen there is only one texture.bind(). Now you understand why I switched to offscreen rendering since one bind() call is "a bit" faster than 1000.

For the future I will switch to 2048x2048 sprite sets, I will pack all terrain sprites into one set and I will start using begin/embedded/end. Thanks for the tipps so far.

_________________
http://www.p1sim.org - Economy/Logistics simulaton based on Java and Slick2D


Top
 Profile  
 
PostPosted: Mon Sep 24, 2012 9:04 pm 
Offline
Regular
User avatar

Joined: Mon Feb 07, 2011 8:48 pm
Posts: 182
Location: United Kingdom
davedes, using your updated example I now get an error on this line on my laptop:

Code:
lightsImage = Image.createOffscreenImage(container.getWidth(), container.getHeight());


It says it could potentially be an OpenGL driver issue. Is this a limitation on the card on that machine?

_________________
Mirage Realms - A free, retro, 2D MMORPG being developed using Slick2D and TWL


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 46 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: CaptainJester and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group