Sign in to follow this  

loading spritesheets into directx?

This topic is 3635 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm completely baffled here. how can I efficiently load a spritesheet into directx and render it on 3D space (not on sprites but on quads)? Right now my idea is to load the entire texture in bit by bit, frame by frame, and go from there. BUt it feels kind of messy. [Edited by - chillypacman on January 4, 2008 4:06:30 PM]

Share this post


Link to post
Share on other sites
Have a large texture with all the frames loaded. The bigger the better, to minimize state switches. Then when rendering quads you just modify the texture coords. For example if there are 4 frames in a column, the top left tex. coords are (0,0)(0,0.25)(0,0.5)(0,0.75) and bottom right are (1.0,0.25)(1.0,0.5)(1.0,0.75)(1.0,1.0) from top to bottom if I am not mistaken.

Share this post


Link to post
Share on other sites
As far as loading, D3DX utilities should provide you with a function to load an image onto a texture surface. If your sprite sheet is not amenable to calculating frame coordinates algorithmically, you may need to do some processing on the texture in a paint program to line things up in a regular (or at least predictable) grid. You may want to have separate textures for related sprites or sprites of similar size to make the algorithm neat and easy. Once you're able to generate the coordinates, just pass those off as texture coordinates to the render call.

As far as what darkelf said, its not always true that bigger sheets are better (although it would, as he said, minimize context switching). Unfortunately, some cards have limitations on texture size and dimension. Many older cards require that textures have a dimension that is a power of 2 (eg 1,2,4,8,16...156...2048) and some of those require that textures be square. Generally, you shouldn't have to worry about maximum dimensions being any smaller than 2048x2048 (I believe all Geforce1 and Radeon cards support up to 2048, and you're not likely to support anything older than that ;)), but some old cards had limits as small as 256x256.

Generally speaking, power-of-two textures are more optimal, even when the hardware supports non-power-of-two (NPOT) textures.

Share this post


Link to post
Share on other sites
I actually made a sample last week that makes a basic sprite class using the ID3DXSprite interface in D3D9. It loads up a sprite sheet and animates the different frames, and supports movement, scaling and rotation of the sprite. It also handles the "power of 2" problem via scaling. There's also some code for generating a bounding box for collision detection, which is used to let you move the sprite around the screen and stay within the window boundaries.

I've never really created a sample before and its likely I didn't handle everything in the most efficient or easy to understand way, but it's all documented and I think it should at least give you a basic idea of where to start with regards to sprites in D3D. I also didn't use DXUT because I wanted to show how to handle some of the basics of Win32, but in retrospect it doesn't seem like that was such a great idea.

Anyway, you can download it here if you'd like.

Share this post


Link to post
Share on other sites
Quote:
Original post by chillypacman
I'm just not sure about one thing, how do I set up texture coordinates?
What do you mean by "set up texture coordinates"? For rendering or for initialising it?

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by chillypacman
I'm just not sure about one thing, how do I set up texture coordinates?
What do you mean by "set up texture coordinates"? For rendering or for initialising it?


like when rendering, if I have a 512*512 texture, how can I tell directx to only render a portion of the entire texture (like a block of 64*64 on the top left corner)?

Share this post


Link to post
Share on other sites
Quote:
Original post by chillypacman
Quote:
Original post by Evil Steve
Quote:
Original post by chillypacman
I'm just not sure about one thing, how do I set up texture coordinates?
What do you mean by "set up texture coordinates"? For rendering or for initialising it?


like when rendering, if I have a 512*512 texture, how can I tell directx to only render a portion of the entire texture (like a block of 64*64 on the top left corner)?
That depends how you're rendering. If you're using ID3DXSprite, you use the RECT pointer passed to ID3DXSprite::Draw(). If you're passing individual vertices and using Draw[Indexed]Primitive, you set them up as part of the vertex structure, where a 64x64 area of a 512x512 image would have texture coordinates of (0, 0) to (0.125, 0.125).

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by chillypacman
Quote:
Original post by Evil Steve
Quote:
Original post by chillypacman
I'm just not sure about one thing, how do I set up texture coordinates?
What do you mean by "set up texture coordinates"? For rendering or for initialising it?


like when rendering, if I have a 512*512 texture, how can I tell directx to only render a portion of the entire texture (like a block of 64*64 on the top left corner)?
That depends how you're rendering. If you're using ID3DXSprite, you use the RECT pointer passed to ID3DXSprite::Draw(). If you're passing individual vertices and using Draw[Indexed]Primitive, you set them up as part of the vertex structure, where a 64x64 area of a 512x512 image would have texture coordinates of (0, 0) to (0.125, 0.125).


oh right, yeah I'm doing it as vertices. So I have to play around with the vertex texture coords then? Would that mean I'd have to lock the vertex buffer every render pass to adjust the texture coordinates? Since that seems kind of inefficient.

Share this post


Link to post
Share on other sites
Quote:
Original post by chillypacman
oh right, yeah I'm doing it as vertices. So I have to play around with the vertex texture coords then? Would that mean I'd have to lock the vertex buffer every render pass to adjust the texture coordinates? Since that seems kind of inefficient.
Yup. If any part of the vertex changes, you need to update the vertex buffer, which means locking. There are ways around it, such as using multiple streams (Which almost certainly won't help since the problem is the lock, not the amount of data transferred), or using a shader to spit out texture coordinates based on something like a a shader constant or a 1D texture.

Share this post


Link to post
Share on other sites
well if thats the case wouldn't it just be easier to split the animation into severel seperate images, load them up as seperate textures and iterate through them instead?

Actually they both seem to be as inefficient as each other. Guess I'll make do with one or the other...

Share this post


Link to post
Share on other sites
Quote:
Original post by chillypacman
well if thats the case wouldn't it just be easier to split the animation into severel seperate images, load them up as seperate textures and iterate through them instead?

Actually they both seem to be as inefficient as each other. Guess I'll make do with one or the other...
Yes, except if you have all the sprites on one texture, you can render all sprites that use that texture in one DrawPrimitive call. If you're only rendering one or two sprites, then using one sprite per textuer might be more efficient, but not by a lot. If you're rendering a worst case of 1000 sprites, and each one is on a different frame of animation, then you'd need to make 1000 DrawPrimitive calls and 1000 SetTexture calls per frame to render them all. If you lock the vertex buffer each frame to update the texture coordinates, you can do it in one call.

DrawPrimitive calls are expensive, Lock calls less so (Usually, depending on the exact timing, etc). If your code is written in a modular way it should be reasonably easy to swap the code and profile both to find the most efficient.

Share this post


Link to post
Share on other sites

This topic is 3635 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this