Why Use a Sprite Sheet Rather Than Individual Images

Why use a sprite sheet rather than individual images?

The aim is to reduce HTTP requests. In addition, sometimes the compressed sprite will weigh less than the original images.

Recently I had a website with a lot of transparent gradients (white to trans, grey to trans) and some black and white on transparent images. By putting them all in a sprite and reducing the colors in the png to 8 I could get the sprite to be smaller in filesize than the original images (just... it was about a 0.5% saving). By reducing the number of HTTP requests from 10 to 1 though meant the site loaded faster (if measuring time from first connection to all data transferred).

In that case, a measurable increase was found.

I agree though that it's possible to mess things up and to end up with a larger sprite than needed, especially if you aren't using PNG compression.

Note two years after posting this – if you are using SSL, you should look into SPDY (my note in a further two years will mention HTTP 2.0 instead of SPDY!). SPDY negates the benefits of spriting.

What are the pros and cons of a sprite sheet compared to an image sequence?

Performance is better for sprite sheets because you have all your data contained in a single texture. Lets say you have 1000 sprites playing the same animation from a sprite sheet. The process for drawing would go something like.

Set the sprite sheet texture.
Adjust UV's to show single frame of animation.
Draw sprite 0
Adjust UV's
Draw sprite 1
.
.
.
Adjust UV's
Draw sprite 998
Adjust UV's
Draw sprite 999

Using a texture sequence could result in a worst case of:

Set the animation texture.
Draw sprite 0
Set the new animation texture.
Draw sprite 1
.
.
.
Set the new animation texture.
Draw sprite 998
Set the new animation texture.
Draw sprite 999

Gah! Before drawing every sprite you would have to set the render state to use a different texture and this is much slower than adjusting a couple of UV's.

Are image sprites actually more efficient than separate images?

Using an image more than once in a page doesn't mean that there is one copy of the image for each place where it is used.

If it did, a page like this demo fiddle would use around 7 GB of memory. It doesn't.


Loading one image is always faster than loading several images. Reducing the number of requests is important when optimising the performance of a site. The fact that the internet is designed to transmit small packages only makes the impact of loading several small images less than it could have been.

LIBGDX is it better to use spritesheet or individual images?

Since the other answers here are not pointing you in the wrong direction, but aren't 100% accurate, I'll add a more detailed explanation.

In case of an animation it should not make a difference performance-wise!

Whether you use a spritesheet or individual images, they will only be sent to the GPU once. The only difference with spritesheets is that you just bind the texture once and you won't be forced to change it anymore when rendering different things.

But this does not really apply to your hero animation. Whether you use a spritesheet or an individual image, in every frame you need to bind the texture again, and draw either just a part of it (in case of spritesheet) or the whole image (in case of individual images), because in between two frames, you also render other non-hero things.

An exception to this would be, if you draw several heroes in one frame. Using individual images, you would have to switch the texture every time, because the heroes are probably not synced. In case of a spritesheet, you bind the texture only once and then draw all heroes with that once sheet-texture (only a single texture-bind will happen in this case).

However you will for sure gain a performance increase, if you make your character-animation-spritesheet a part of another, "bigger" spritesheet, where also other textures are packed into. This way you can draw your character and other things again with just a single texture-binding.

The only problem with spritesheets is, that they tend to waste some space. Especially on mobile devices when you are forced to use POT (power of two) sized textures, this can make a difference.

Multiple Images vs spritesheet

The number of concurrent HTTP/1 connections to a host is limited to about 6. Assuming a latency of 100ms, the about 60 images in the posted sprite would take at least a whole second to download (probably more, since HTTP requests and answers need to be generated and parsed).

Since the size of the sprite image is about the same as the individual sprites and image processing is blazingly fast (I'd estimate well below <100 ms for all 60 images together), using sprites saves amazon about 900ms of load time, a noticeable impact - and that's in theory, without accounting for the huge overhead of having to serve 60x the number of requests they would have to otherwise.

In summary, use sprites for logos and small images over HTTP/1.

HTTP/2 is designed so that workarounds are no longer needed. Most importantly, multiple requests can be served concurrently over the same TCP connection. Additionally, header compression is designed to compress redundant headers such as User-Agent or Accept.

sprite vs individual images

Normally you will use sprite for change states of particular element, e.g. for the button, not for all the images at once. Benefit of using sprites in that case is not just to save a request, but also to make state changes (say on mouse over) instant.

Sprites VS Larger Images

Good question, the problem that sprites solves is meant mostly when there are many and small images. So instead of making 100 requests to a server you make a single one.

When using large images you won't get much benefit from this concept. Also with larger images, it's better if the first image get's loaded and you could render it to a user and meanwhile load other images.

Third option would be to render some small thumbnails 20x20 pixels JPG files(usually <~10KB size), and then stretch these to the same size as the larger ones. This causes some blurry image but it's understandable what's on the image. Now when the larger images gets loaded you replace the small ones. This requires additional JavaScript execution.

Is there any benefit to using sprite sheets in Java with awt?

Contrary to popular belief, BufferedImage.getSubimage(...) will not create a new copy of image data. It will only be a (live) view of the "parent" image. This is very fast and cheap compared to actually cloning the data array. So, I'd say it makes perfectly sense to use a sprite sheet in this way.

Any changes made to the parent image will be reflected in the subimages and vice versa. From the javadoc:

Returns a subimage defined by a specified rectangular region. The returned BufferedImage shares the same data array as the original image.

In other words, only a small wrapper around the data array is created for each subimage instance. The easiest way to verify this, would be to just try drawing over one of the subimages and see that changes are reflected.

As @MadProgrammer points out, loading a large image once is likely to be faster and more memory efficient than loading many small images.

However, there are some gotchas:

  • A larger image will need a larger continuous block of memory. This might be a problem in a Java VM that has been running for a while, as free memory gets fragmented (probably less a problem in a modern VMs, and no problem at all, if you load your image once, early in your game).
  • After you have created a subimage, the memory for the parent image cannot be freed until the subimage is freed (because of the shared data array). If this is not what you want, you need to manually create copies of the subimages.

Do sprite sheets provide any advantage during rendering?

I suspect @Bergi has it just right.

I did the following quick perf test drawing a sprite 10000 times using canvas-frames and then using clips from a spritesheet.

On my machine (win8/2GHz/4Core), clipping from a spritesheet was always faster, but both canvas-frames and spritesheet-clipping occurred so quickly that there was no significant rendering speed benefit using one method or the other.

Given no speed improvement between the 2 methods, we're left with Bergi's good conclusion that the extra setup plus memory overhead with canvas would tilt a decision towards clipping a spritesheet. Also, the canvas-frame solution would certainly lag on mobile--mobile doesn't do canvas well.

var canvas=document.getElementById("canvas");var ctx=canvas.getContext("2d");var cw=canvas.width;var ch=canvas.height;

var cframes=[];var iw,ih,iw10;
var img=new Image();img.onload=start;img.src="https://dl.dropboxusercontent.com/u/139992952/multple/avatars.png";function start(){
var iw=img.width; var ih=img.height; var iw10=parseInt(iw/10); var iterations=10000;
for(var i=0;i<10;i++){ var c=document.createElement('canvas'); var cx=c.getContext('2d'); c.width=iw10; c.height=ih; cx.drawImage(img, iw10*i,0,iw10,ih, 0,0,iw10,ih); cframes.push(c); }

var t1=performance.now(); for(var i=0;i<iterations;i++){ ctx.drawImage(cframes[i%10],10,0); } var t2=performance.now();

var t3=performance.now(); for(var i=0;i<iterations;i++){ ctx.drawImage(img, (i%10)*iw10,0,iw10,ih, 10,ih,iw10,ih); } var t4=performance.now();
alert(iterations+' draws. Canvas-frames:'+parseInt(t2-t1)+'ms, spritesheet-clips:'+parseInt(t4-t3)+'ms');
}
body{ background-color: black; padding:10px; }#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>


Related Topics



Leave a reply



Submit