Sign in to follow this  

Texture sheets vs individual textures?

This topic is 2084 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 nearing the finish of a project and on its finish I want to start a bigger project, so in my spare time I've been planning it out.
The new project I'm aiming for a powerful 3D engine, with fast and beautiful graphics.

Naturally I want as best performance as I can get. One thing I came across suggested changing the texture often can have more of an overhead than just sending it all in one (similar to why spritesheets are beneficial)
Would it be beneficial to have groups of textures intended for use with a specific shader or different instances of a single object, in one texture sheet or would it be better to keep all textures separate.

To let you know what I have in mind here is a purely hypothetical situation, imagine a character customizable by legs, body and head. The customization would be only textures, so the same models could simple be instanced for multiple characters. In this case, would it make much of an impact to send all possible head, body or legs (respective of what is being drawn) customization textures in a sheet, or would I be better of letting each texture be sent as its needed?

It seems to me like a memory vs cpu problem, regardless it'd be worth knowing if each are beneficial in their own way or if one is superior in a notable way, etc. Because it would allow me to decide between putting in support for both or emphasis on one.

Any and all help is appreciated,
Thanks in advanced,
Bombshell

Share this post


Link to post
Share on other sites
It probably doesn't matter much with current graphics cards, since most textures are at least 128x128, the cost of uploading the texture header is amortized over the size of the image data. Back when we had 16x16 sprites, the header was a significant fraction of the actual data uploaded, which encouraged the use of sprite sheets. And of course CPU-GPU latency also plays a part in this.

Now of course, you can only upload so much different textures to a shader before getting confused with all the texture variables (or simply running out of texture registers), so if you can place for instance sixteen 32x32 textures in a single 128x128 texture, it would definitely be a good choice. But don't go placing four 1024x1024 textures in a 2048x2048 texture because you'll run into memory access issues (as well as fragmentation, but don't quote me on this as I don't know how GPU's manage their memory).

That said, for characters, you do want to use those weird textures with leg/arm textures stuck around, because it is a more compact representation than just uploading each part separately (if you did the latter, you would end up uploading a lot of background, unused data). It also works better with UV's, too.

EDIT: by the way, you could check out texture arrays if you use D3D or OpenGL - I suppose they aren't just an array of textures but also use some tricks to make the use of texture arrays more efficient. In a way, sprite sheets could be viewed as a hack compared to texture arrays.

Share this post


Link to post
Share on other sites
As an architectural suggestion, don't design the renderer in such a way that it cares. As far as it's concerned, it just takes black-box textures, meshes, materials, etc. and feeds them to the graphics hardware.

*On top of that* you can implement an atlasing system-- a part of the character logic would be an excellent place to put this.

This way, you get the best of both worlds :)

Share this post


Link to post
Share on other sites
what do you mean by an atlasing system? I did a quick google on atlasing and it came up with stuff about run of the mill UV unwrap textures?
Or do you mean a system which creates unique atlases from pieces so unique combinations of character traits will be put together in a characters own texture?
It seems DirectX has its own system built in for handling such things, so I may give it a look, maybe make my own if the one if the directX one isn't what It thought.

Anyway all this seems targeted at memory so I'll go ahead and assume cpu-gpu should be no issue for the next proposition.
Wouldn't it be even more space efficient to take already made textures and rearrange the triangles in a most space efficient formation, E.G. going from islands of textures into shards of textures.
Obviously the texture itself would look a mess until unwrapped on the object.
The only real problem I see with that (and please correct me if I'm wrong) is the messiness that often comes with UV edges (which tbh I never understood how such sampling artefacts could happen.)

Share this post


Link to post
Share on other sites
[quote]Wouldn't it be even more space efficient to take already made textures and rearrange the triangles in a most space efficient formation, E.G. going from islands of textures into shards of textures.[/quote]
No, you're overanalyzing here. There's a line between optimizing computational bottlenecks and shaving a megabyte off the GPU memory footprint of your program. Optimization is best done by first running a non-optimized code, running it and observing where the bottlenecks are, and optimizing the relevant parts.

Share this post


Link to post
Share on other sites
[quote name='bombshell93' timestamp='1333071329' post='4926516']
Naturally I want as best performance as I can get.[/quote]I suggest to get the job done first. I have spent too much time in early optimization only to find out it was not worth it. Iterate.
[quote name='bombshell93' timestamp='1333071329' post='4926516']
One thing I came across suggested changing the texture often can have more of an overhead than just sending it all in one (similar to why spritesheets are beneficial)
Would it be beneficial to have groups of textures intended for use with a specific shader or different instances of a single object, in one texture sheet or would it be better to keep all textures separate.[/quote]Keep all textures separate. That's the way they're supposed to be used. Please note that using texture sheets mandates special behavior when it comes to (example) a scrolling texture shader. I can tell by experience this is going to be problematic. It is less so in Shader Model 4 and later thanks to texture arrays but I'd still stay out of texture sheets for a while.
[quote name='bombshell93' timestamp='1333071329' post='4926516']
To let you know what I have in mind here is a purely hypothetical situation, imagine a character customizable by legs, body and head. The customization would be only textures, so the same models could simple be instanced for multiple characters. In this case, would it make much of an impact to send all possible head, body or legs (respective of what is being drawn) customization textures in a sheet, or would I be better of letting each texture be sent as its needed?[/quote]I'd send everything as needed. It would not be much of a performance concern right now. Without raw performance data to look at, taking this decision is a risk.

Share this post


Link to post
Share on other sites
What I do is using separated textuers by default. For the very obvious reason that we need every pixel to maximize the details. And for tiling, mipmapping, et cetera.

BUT, props like plants, junk, cans, bricks, craps, bullet hole decals and all other stuff that usually comes in large numbers at the same time may benefit a bit from sheets. If you model 20 different plants/trees, all using the same texture(s), you can sort them and only do 1 texture switch instead of at least 20. Foliage is a special case anyway, if you decide to use blended materials and sort on depth instead of material. If each different foliage-object uses a different texture, you might end up switching a lot in a dense jungle. Same trick can be done for furniture. A set (couch, chair, coffee table) may all use the same materials so why not combining them in one sheet?

So if possible, we share the texture amongst multiple objects. But only if the textures are not repeated (or at least only horizontal or vertically), and if the quality doesn't suffer too much. Plus it needs to be worth it. If it only saves one texture switch... that does not make you win the performance war.

Share this post


Link to post
Share on other sites
[quote name='Bacterius' timestamp='1333071972' post='4926520']
But don't go placing four 1024x1024 textures in a 2048x2048 texture because you'll run into memory access issues (as well as fragmentation, but don't quote me on this as I don't know how GPU's manage their memory).
[/quote]

I'm going to have to quote you on that [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

Allocating larger blocks of memory would decrease fragmentation, because fragmentation is inherently caused by small allocations. It would, however, increase the chance of not being able to find a memory block large enough for the allocation, i.e. increase the effect of fragmentation.

That's the biggest reason for using texture atlases in modern games IMO; I automatically combine textures smaller than 128x128 so that if someone creates a thousand 1x1 textures at different times, they don't play hell with the memory (I've actually seen artists do this, and it was the source of some hard to track down memory issues). Most modern cards will do this kind of management automatically by allocating textures in pools to keep same sized textures together, but you can't depend on it being available.

Its similar to the near / far view planes in that the problem arises not from small or large allocations, but the difference between the smallest and largest allocations.

Share this post


Link to post
Share on other sites
so to conclude,
Only use sheets when a group of relatively smaller textures are expected to swap frequently.
Large textures try to avoid but if forced to use texture arrays rather than large sheets of textures.

Share this post


Link to post
Share on other sites
[quote name='bombshell93' timestamp='1333124245' post='4926721']
so to conclude,
Only use sheets when a group of relatively smaller textures are expected to swap frequently.
Large textures try to avoid but if forced to use texture arrays rather than large sheets of textures.
[/quote]

IMO a qualified yes - implementing atlases isn't trivial, but its not any more difficult to implement them in an engine that doesn't use them than it is to plan for them ahead of time. The layer is inserted between the mesh data (which should still be constructed as if it used a regular texture, i.e. uv in the [0,1] range) and the renderer (which still takes a texture and uv data). Alternatively you can use an offline tool to combine textures, which just takes a bunch of meshes and textures and does the combining / uv changes.

The former is better if you can't reliably predict which models / textures will be used together (because it generates the textures dynamically). The latter is better if you can (because it removes the (small) overhead during runtime and is simpler).

Either way, its only really needed if you're streaming data into VRAM. If you have a more "typical" use case for an indie type project - where the data set is a good bit smaller than VRAM and you don't have to constantly stream it in an out (i.e. "levels" as opposed to an "open world") - its overkill and your time can be better spent on other things.

To sum up: don't implement it until you need it, it won't be more difficult later on.

Share this post


Link to post
Share on other sites
[quote name='Bacterius' timestamp='1333071972' post='4926520']
It probably doesn't matter much with current graphics cards, since most textures are at least 128x128, the cost of uploading the texture header is amortized over the size of the image data. Back when we had 16x16 sprites, the header was a significant fraction of the actual data uploaded, which encouraged the use of sprite sheets. And of course CPU-GPU latency also plays a part in this.
[/quote]

I'd suggest that having to break draw call batches is a far more important consideration than size of header vs size of data here.

You're suggestion of texture arrays is spot on though; atlassing can get complex and messy real quick, arrays are quite trivial (the only real restriction being that all textures in the array must be the same size and format). I wouldn't even consider a texture array as falling into the realms of "premature optimization" given the use case that the OP has outlined.

Share this post


Link to post
Share on other sites
[quote name='turch' timestamp='1333115156' post='4926680']
Allocating larger blocks of memory would decrease fragmentation, because fragmentation is inherently caused by small allocations. It would, however, increase the chance of not being able to find a memory block large enough for the allocation, i.e. increase the effect of fragmentation.

That's the biggest reason for using texture atlases in modern games IMO
[/quote]

The biggest reason they were created originally was batch overhead on the CPU, thats not to say fragmentation is not important. Fragmentation can be solved without atlasing

If batch overhead is not a concern I wouldn't go out of your way to create a massive atlas of textures via a code driven system. These days its probably not worth it. On the other hand you might have animate textures that you do want to have on a sprite sheet for a particle system, this can be more efficent (or use texture arrays on newer hardware).

An experienced artist will create an optimal texture by combining all the textures required for one object on to a single texture and mapping it as required.

Share this post


Link to post
Share on other sites

This topic is 2084 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