Sprite Sheets and Texture Splitting

Started by
3 comments, last by MichaelNIII 11 years, 1 month ago

Hey guys, need some opinions/input on the best way to handle this.

Using DirectX 9, for reference.

I've recently started implementing animated textures into my engine, which included the addition of sprite sheets.

I've made it to the point that the resource hierarchy (texture management) will let me reference static textures and animated textures interchangeably, and the sprite sheet textures (plus separation data) are loaded properly.

Now I've come to a bit of a crossroads, and am hoping there's a better way to handle this.

So, I've got my sprite sheet loaded as a texture, and now need to split it off into individual frames.

I can setup a system that will modify texture coordinates and rotation properties to grab the proper image off of the sprite sheet, without cutting the texture up in memory at all. This, however, would add some overhead on per-frame calculations and increase the amount of data being sent down the shader pipeline a bit, especially considering I'll need to re-add transparent pixel data around the edges of most of the grabbed sections. Plus it'll be a decent bit of work coding wise.

The second option is to split the textures up when the sprite sheet is loaded, copying them to new texture resources, so I don't have to modify texture coordinates (et cetera) at all, I just have to pass a different texture pointer. This would add some additional memory overhead, though, and essentially eliminate 80% of the purpose of using sprite sheets in the first place.

So, I'm hoping there's a third option I'm missing. I was really hoping there was a way to simply set up a texture "reference" (that points to a specific subset of a texture) without having to physically make a new texture to store it, but I haven't seen anything of the sort.

Anyways, any input is greatly appreciated. Thanks in advance!

Advertisement

Go for option number 1.

don't cut the texture up but simple adjust the texture coords (of the geometry, probably quads) when drawing different frames.

You could have each sprite sheet linked with a file defining the area of each frame. When setting a different frame, simple look up the texture coordinates for that particular frame.

You can easily pre-define texture coordinates and the overhead (even when doing it as a one time only event) is minimal.

This is the code that I use to do option #1 for my game:


void get_tex_coords( struct texture_t* t, struct Rect* r, D3DXVECTOR2* tc )
{
    tc[0].x = r->x1 / t->width;
    tc[0].y = ( r->y1 / t->height );
    tc[1].x = r->x2 / t->width;
    tc[1].y = ( r->y1 / t->height );
    tc[2].x = r->x2 / t->width;
    tc[2].y = ( r->y2 / t->height );
    tc[3].x = r->x1 / t->width;
    tc[3].y = ( r->y2 / t->height );
}

Since it was originally written for OpenGL, I modified it a bit to make more sense for Direct3D users. It's really simple once you understand that you're just getting the coordinates by getting the x,y position followed by the with,height while adding the x,y coordinates. That will give you your exact coordinates for each sprite on the sheet! smile.png

Shogun

You can easily pre-define texture coordinates and the overhead (even when doing it as a one time only event) is minimal.

This is the code that I use to do option #1 for my game:


void get_tex_coords( struct texture_t* t, struct Rect* r, D3DXVECTOR2* tc )
{
    tc[0].x = r->x1 / t->width;
    tc[0].y = ( r->y1 / t->height );
    tc[1].x = r->x2 / t->width;
    tc[1].y = ( r->y1 / t->height );
    tc[2].x = r->x2 / t->width;
    tc[2].y = ( r->y2 / t->height );
    tc[3].x = r->x1 / t->width;
    tc[3].y = ( r->y2 / t->height );
}

Since it was originally written for OpenGL, I modified it a bit to make more sense for Direct3D users. It's really simple once you understand that you're just getting the coordinates by getting the x,y position followed by the with,height while adding the x,y coordinates. That will give you your exact coordinates for each sprite on the sheet! smile.png

Shogun

Yeah, that's the easy part. smile.png Unfortunately, I can't precalculate values in this case.

The sprites can be rotated on the sheet, and will need to have extra transparent space added on to them, which means the calculations will have to be done in the shaders. It's not the calculations I'm worried about anyways, it's the extra data being sent down the pipeline.

For instance, my model shader takes 4 textures (for various lighting effects, etc).

That means that for every model drawn, just to use sprite sheets (and remember these are ONLY in use if the texture is animated, which is the exception rather than the rule) I have to include:

-8 extra float2's (a texture coord range for each texture, specifying where on the sprite sheet to take it from)

-Another 16 float2's (final texture width/height and the texture offset, so transparent space can be added in the shader and the texture can be properly aligned)

-8 boolean values (specifying if the texture is rotated on the sprite sheet)

Plus all the calculations to make those function. All done in the shader.

Feels like a huge chunk of data to be sending down the pipeline with every shader for functionality that's not going to be used in the majority of cases... Maybe I'm worrying over something that won't really be causing any serious issues. It likely won't cause any performance hit whatsoever, just feels like I'm adding a lot of bloat to the system.

Thanks for the input though guys.

If I am reading this right your issue is you should not be rotating the objects on the sprite sheet, one huge issue would be you must recalculate the sprite sheet each time you rotate it, or must provide enough room on the sheet to allow the object to rotate freely without intersecting the other sprites on the sheet. This in itself Is a good bit of wasted room, expically the more rectangular the sprite is. Is there a reason why you can not apply a scaling and rotation to the triangle that you are mapping it to, or if your using the sprites class using the 2d transform on it?

This topic is closed to new replies.

Advertisement