SpriteLibrary: Efficient render of sprites

http://i.imgur.com/uDQH2.png


Code : http://code.google.com/p/petomancer/downloads/detail?name=SpriteLibrary.zip&can=2&q=

Pros :
1) static sprite speed: can render 1500000 sprites at 149 fps ( 0% cpu load, speed limited only by graphics card ). As long as you don't change them (add, move, delete, change image).
2) automatic management of texture atlas: if you add 300 different images it wont crash because 300 images cannot be put in a 1024x1024 texture, it will create an extra spriteMesh that contains the extra different images.

Cons:
1) Animated sprites : fpswise thats not its strong point it can only render 60000 animated sprites at 444 fps. Animation speed sucks because it is done on cpu and not on hardware.
2) Culling: no culling is performed.

Usage example:
[java]
@Override
public void simpleInitApp()
{
spriteManager = new SpriteManager(1024, 1024, SpriteMesh.Strategy.KEEP_BUFFER, rootNode, assetManager );
getStateManager().attach(spriteManager);

File npcLocation = new File(FileUtilities.ASSET_DIRECTORY+"2d/npc/");
String[] npcList = npcLocation.list(FileUtilities.SUPPORTED_IMAGES);
for (int i = 0; i < npcList.length; i++)
{
Sprite sprite = new Sprite(spriteManager.createSpriteImage("2d/npc/"+npcList, true));
sprite.setPosition(i,0,0);
}
}
[/java]
6 Likes

Cool, any interest in adding this as a SDK plugin?

Looking good. By the way, any reason why the SpriteManager is an AppState and not a Node or Control? In some cases the user might want to have sprites in both the root and gui nodes for example.

Also I guess it should use the asset manager instead of files to load the images.

@normen said:
Also I guess it should use the asset manager instead of files to load the images.

I think it already does since the SpriteManager takes it as an argument and the createSpriteImage() takes a String. The only part that uses files is the listing of the images which makes it simpler to write the test program.

Right, looking at the code I see dependencies on awt though, so it will not work on android yet :confused:

  1. about making a plugin, i haven’t done a plugin before, and i need to take a vacation because i got tired of programming low level stuff.
  2. About spriteManager, it takes an argument the “rootNode” don’t know if you can cheat it by passing the guiNode as a “rootNode”.
  3. Also about not making it as a AppState, you can use a spriteMesh, but a spriteMesh won’t protect you if you add more AtlasSprites (different images that have to be stored in a texture 1024x1024) than its TextureAtlas can hold.
  4. it uses assetManager to load images, but it locates images under a folder by using java files.
  5. about awt dependencies : it uses BufferedImages because

    a) the user could theoretically want to create procedurally generated sprites.

    b) all BufferedImages are combined into 1 TextureAtlas to form the final texture.

    java is supposed to be cross platform. Doesn’t android have BufferedImage class ?

No android is not pure java, no awt there( and no swing as well as some other stuff in the java.* package), thats why google and oracle fight , because oracle fears a splitting of its business platform language.



Thw whole processing could be done with the jme own image class, its a bit moe of handwork however, since you would need tow ork directly on the ufffer (or write the helper functions first to get and set color of a specific pixel, I guess this would be quite nice as a addition ot the core class)

@tralala said:
http://i.imgur.com/uDQH2.png

Code : http://code.google.com/p/petomancer/downloads/detail?name=SpriteLibrary.zip&can=2&q=

Pros :
1) static sprite speed: can render 1500000 sprites at 149 fps ( 0% cpu load, speed limited only by graphics card ). As long as you don't change them (add, move, delete, change image).
2) automatic management of texture atlas: if you add 300 different images it wont crash because 300 images cannot be put in a 1024x1024 texture, it will create an extra spriteMesh that contains the extra different images.

Cons:
1) Animated sprites : fpswise thats not its strong point it can only render 60000 animated sprites at 444 fps. Animation speed sucks because it is done on cpu and not on hardware.
2) Culling: no culling is performed.

Usage example:
[java]
@Override
public void simpleInitApp()
{
spriteManager = new SpriteManager(1024, 1024, SpriteMesh.Strategy.KEEP_BUFFER, rootNode, assetManager );
getStateManager().attach(spriteManager);

File npcLocation = new File(FileUtilities.ASSET_DIRECTORY+&quot;2d/npc/&quot;);
String[] npcList = npcLocation.list(FileUtilities.SUPPORTED_IMAGES);
for (int i = 0; i &lt; npcList.length; i++)
{
Sprite sprite = new Sprite(spriteManager.createSpriteImage(&quot;2d/npc/&quot;+npcList, true));
sprite.setPosition(i,0,0);
}
}
[/java]


Hey @tralala,

Just saw your post in my other thread and am interested in trying this out. How hard of a performance hit would it take to change the sprites? In the game I'm making, I would need to be able to change from one sprite to another and back on the fly, depending on how the game conditions changed.

Either way, 1,500,000 sprites looks impressive. I'll definitely try this out soon.
1 Like

@tralala , you shader is added to the shader library. And i did links to this topic. Thank you!



http://code.google.com/p/jme-glsl-shaders/downloads/list

1 Like

@anirak :

if you change the positions, colors, size etc it will have to resent all data to the gpu, all from start.

if you do it every frame [worst possible case], then you will have the same performance as Animated sprites = 444fps for 60000 sprites.



@mifth : thank you

That’s pretty neat. Only downside is you can’t rotate point sprites :frowning:



Very fast though I had a big solid block of 1.5 million sprites at only ~20-25 fps.

Huuum, I’m trying to figure it out why I can’t change the size of the sprites. For some reason the sprites are only drawn at a 64x64 size. Searched everywhere but failed to find the reason. Can someone give me a hand? Maybe @tralala or anyone with some experience can help me out?

@shirkit said:
Huuum, I'm trying to figure it out why I can't change the size of the sprites. For some reason the sprites are only drawn at a 64x64 size. Searched everywhere but failed to find the reason. Can someone give me a hand? Maybe @tralala or anyone with some experience can help me out?


Are you trying to get them bigger? That's important information because many GPUs clamp the max size of point sprites on screen. There is a cap to query for this max size but JME doesn't expose these cap values yet as far as I know.

It's frustrating because I have a whole handful of point-sprite based particle effects that look like crap on these cards.
@pspeed said:
Are you trying to get them bigger? That's important information because many GPUs clamp the max size of point sprites on screen. There is a cap to query for this max size but JME doesn't expose these cap values yet as far as I know.

It's frustrating because I have a whole handful of point-sprite based particle effects that look like crap on these cards.


Yeah I want them bigger. I have a GTX660M over here, but I don't know if that matters in this case.

I've looked upon everything I knew, everything seems right. The texture has the right size after loaded, it is passing the right sized texture (a big one) into the material (and then to the GPU), but something doesn't seems right. Can you take a look quick look at the Particle.vert shader @pspeed ?
@shirkit said:
Yeah I want them bigger. I have a GTX660M over here, but I don't know if that matters in this case.

I've looked upon everything I knew, everything seems right. The texture has the right size after loaded, it is passing the right sized texture (a big one) into the material (and then to the GPU), but something doesn't seems right. Can you take a look quick look at the Particle.vert shader @pspeed ?


There is nothing wrong with your shader. This is not an issue of texture size or anything else. You are being hit by the max size issue. If you search around on the web then you can find that this is a commonly reported problem... and very frustrating.

For example, see here: http://www.informit.com/articles/article.aspx?p=770639&seqNum=7
Quote from that page:

One serious limitation to the use of point sprites is that their size is limited by the range of aliased point sizes (this was discussed in Chapter 3, "Drawing in Space: Geometric Primitives and Buffers"). You can quickly determine this implementation-dependent range with the following two lines of code:

GLfloat fSizes[2];
GLGetFloatfv(GL_ALIASED_POINT_SIZE_RANGE, fSizes);

Following this, the array fSizes will contain the minimum and maximum sizes supported for point sprites, and regular aliased points.


Your mobile card is probably limiting it point sprites to 64 screen pixels. The only way around this is to render textured quads instead of point sprites. I hope soon that JME exposes these kinds of caps so that our apps can switch to the fast point sprite method when there is no size limit (like on non-mobile nvidia cards) and use a special vert shader + quads in the other cases (like pretty much every ATI card and several mobile nVidia cards).

About point sprites, i struggled with them recently on android

Be warned that OGLES specs do not define that point sprites could be something else than points.

So basically their behavior will differ depending on the hardware.

Some allow textures of any size some limit them to 32x32 some to 64x64 some…to 1x1…pixel.

I have the latter on my nexus one for example.

In short, point sprites are not something you can rely on, on a mobile device.

Paul suggestion to use quads is the way to go unfortunately.

I think it’s perhaps misleading to call it a “texture limit”. It is an on-screen limit. You can use a texture of any size but if the GL_ALIASED_POINT_SIZE_RANGE maxes at 16 then it will never be bigger than 16 pixels on screen.



It seems like 64 is a very common limit since Mythruna’s flames and my water fall test look super duper ugly with teeny-tiny particles (relative to screen size when close to the emitters) on those platforms.

Quads are totally the way to go, since I’m planning going on Android. So yeah ^^ Thank you for your time!

Can a sprite cas shadow and receive a shadow? :roll: