Welcome to MSDN Blogs Sign in | Join | Help

Texture filtering: sprite sheets

You can control what happens when texture filtering reads from past the edge of a texture using the SamplerState.AddressU and AddressV properties. But what if you are using a sprite sheet? The sampler address modes know nothing about how your sprites have been packed together, so when you filter a sprite from a sheet, the GPU will happily sample from outside the area you told it to draw. This causes colors from one sprite to show up along the edges of whatever happens to be packed next to it, which is unlikely to be what you wanted!

Possible solutions:

  • Don't use sprite sheets. This is especially a good idea if you want mipmaps, as it is near impossible to make sprite sheets and mipmaps play nice together.

  • Don't use filtering. Point sampling will never read past the edge of the region you specify, so it has no problem with sprite sheets. But then, point sampling tends to look rather ugly, and who wants that?

  • Roll your own filtering in the pixel shader. If you set the GPU to point sampling mode, you could write a shader that implements bilinear filtering by averaging several point samples, and this shader could know about your sprite sheet and thus avoid reading from outside the current sprite. This is likely to be slower than not using sprite sheets at all, though, so not usually a good idea.

  • Add a gutter region around each sprite. Given this 3x3 source image:
A B C
D E F
G H I

Expand it to 5x5:

a a b c c
a A B C c
d D E F f
g G H I i
g g h i i

Pack the 5x5 version into your sprite sheet, but just draw the inner 3x3 (shown in bold). Now the filtering hardware can happily read past the edge of the specified region, and will pick up sensible color values from the gutter pixels (shown in italic).

Adding gutters by hand soon gets boring, but this is easy to automate. Our Sprite Sheet sample provides a content processor that will pack any number of textures into a sprite sheet, automatically adding the necessary gutters to make filtering work correctly.

Published Wednesday, October 21, 2009 11:25 AM by ShawnHargreaves

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Wednesday, October 21, 2009 3:37 PM by J

# re: Texture filtering: sprite sheets

What would you use instead of sprite sheets?

Wednesday, October 21, 2009 3:45 PM by ShawnHargreaves

# re: Texture filtering: sprite sheets

> What would you use instead of sprite sheets?

Individual textures, one per sprite.

Thursday, October 22, 2009 12:59 AM by Roel

# re: Texture filtering: sprite sheets

Thanks again for your blog, it rocks! Regarding the gutter regions, that would still not work for mip mapping, would it?

Thursday, October 22, 2009 2:55 AM by Lars Viklund

# re: Texture filtering: sprite sheets

I suppose it's largely irrelevant when dealing with regular view-aligned sprites, but wouldn't the 1tx gutter approach be inadequate if viewing the sprite at a shallow angle with anisotropic filtering?

Thursday, October 22, 2009 8:30 AM by Beringela

# re: Texture filtering: sprite sheets

I remember seeing in the Sprite Sheet sample that mipsmaps are generated for the resulting spritesheet it creates.

Why dont spritesheets (with an edge around each sprite) and mipmaps go well together and are there any workarounds other than not using spritesheets or not using mipmaps?

Thursday, October 22, 2009 9:43 AM by ShawnHargreaves

# re: Texture filtering: sprite sheets

Lars: quite right, a single pixel gutter may not be enough when using anisotropic filtering. In that case you could increase the gutter size to match your max anisotropy setting. I've never actually come across this problem in practice, though, since sprite sheets are most often used with 2D graphics, and anisotropic filtering is only relevant in 3D.

Beringela: our Sprite Sheet sample does not create any mipmaps.

Beringela and Roel: actually I think I'll do another post about the problems of mipmapped sprite sheets.

Thursday, October 22, 2009 3:15 PM by Beringela

# re: Texture filtering: sprite sheets

Great, I look forward to you writing about mipmapped spritesheet issues, I am a huge fan of your blog.

The reason I thought the sprite sheet sample used mipmaps is that in SpriteSheetProcessor.cs there is a line at the end of the .Process method that says this:

spriteSheet.Texture.Mipmaps.Add(packedSprites);

Does this not add mipmaps?

Thursday, October 22, 2009 3:19 PM by ShawnHargreaves

# re: Texture filtering: sprite sheets

This line:

   spriteSheet.Texture.Mipmaps.Add(packedSprites);

just adds a single image to the mipchain collection. That's not a series of mipmaps, it's the main texture itself! (if you didn't have a single image in there, there would be no data in the texture at all).

To have a mip chain, you need more than one image, each one half the size of the previous.

Tuesday, October 27, 2009 9:03 AM by Owen Raccuglia

# re: Texture filtering: sprite sheets

Can you explain why there's no gutter between the middle sprites -- E, for example? Why won't textures from D get sampled in to E's left edge?

Great series, by the way.

Tuesday, October 27, 2009 9:51 AM by ShawnHargreaves

# re: Texture filtering: sprite sheets

> Can you explain why there's no gutter between the middle sprites -- E, for example? Why won't textures from D get sampled in to E's left edge?

D, E, etc, refer to pixels, not sprites!

This example was showing how to add a gutter around just a single 3x3 sprite.

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker