1
\$\begingroup\$

I am more a newbie considering game development but I am dealing very often with optimization of games for work and because I am interested in it.

So as far as I know higher texture size need less draw calls if you make serveral objects share the same texture but it takes up more VRAM. Also you have to consider how acuit you want to have your textures.

But the more I thought about the topic I thought there would be a theoretical perfect texture size, correct me if I am wrong.

Thought experimet: Considering you always want the same acuity of your game and you have 4 objects that take the exact same amount of UV space but have different textures.

Then there would be a perfect spot between texture size and number of objects that share the same texture considering your goal is best performance. In this case there would be 4 possibilities:

  • 1 texture where all objects share the same one
  • 2 texture for two of the objects
  • 3 texures where it would be a mix of those above
  • or 4 textures where every object have their own

If performance is your main goal then there would be only one variable to change depending on how acuit you want your game, the acuity, wouldnt it?

Hope you understood my thoughts^^

\$\endgroup\$
  • \$\begingroup\$ Can you guarantee those objects always going to be rendered together in the same frame? \$\endgroup\$ – Simon F Aug 31 '17 at 10:56
  • \$\begingroup\$ I dont have enough reputation to comment -.- Lets say for this experiment yes, but I would be interested in an answer for both ways. \$\endgroup\$ – Lala_Ghost Aug 31 '17 at 11:02
  • 1
    \$\begingroup\$ I'm not accustomed to seeing the word "acuity" used the way you've described here in gamedev circles. Would you say it's equivalent to "texel density," the number of texture pixels in a given span of game world space? \$\endgroup\$ – DMGregory Sep 2 '17 at 12:50
4
\$\begingroup\$

It's very rare in gamedev to have a single optimum / perfect answer to anything - there are so many interacting concerns that we're constantly forced to make judgement calls between.

For instance, to a first approximation, combining textures so we can render more objects in a single pass is preferred, because it saves us draw calls which are often a limiting factor on our game's performace. But if you're not draw call bound (say you're using only a dozen different passes) then you might not see any benefit from this at all. And it's not without downsides:

  • Content rendered in a single pass usually needs to share one set of transform data. (Ignoring instancing for the moment) This is easiest to accomplish with static scene geometry, or small batches of simple dynamic objects that you bake into a shared buffer CPU-side, so it might not even apply to everything you want to render in your scene.

  • Setting up your textures and object UVs to use the atlas rather than their own texture space is an extra step in your asset creation workflow (and possible blocking point if two artists need to work on objects in the same atlas), or an extra process you need to build into your importer pipeline if it doesn't do it out of the box.

  • If your typical game scenes use only a few objects but in random combinations, pulling in a giant pre-baked atlas that covers every combination might make your loading times longer than you'd need if you just loaded each texture individually.

  • You could instead generate the atlas dynamically, hosting only the textures you need for the present scene, but that management layer adds a lot of complexity to your code, which might not be worth the development effort it will cost you if you're not seeing big wins from saving draw calls.

We're also limited by the maximum texture size that a given platform will support (particularly on older platforms that don't let us combine textures in arrays), which can put an upper bound on how many objects we can combine onto a single texture.

Finally, increasing texture size isn't the only way to improve detail. You're unlikely to want to paint every square meter of the game world in 4096 resolution, just in case a player with a 4K monitor decides to ram their camera straight into every wall & prop to see it as magnified as possible. You might instead layer repeating detail & grime textures at high magnification to break up interpolation artifacts. (Those textures might be in their own separate array, since you need a second sample anyway)

This is just a rough sampling of some of the different concerns a game development team would need to weigh when deciding on a batching / atlassing strategy, and it doesn't have a single common answer or formula that will be right for every game.

\$\endgroup\$
2
\$\begingroup\$

A 1024x1024 texture would take up as much space as four 512x512 textures in VRAM and the number of draw calls will be equivalent.

The win with using 1 larger texture instead of 2 smaller is that you load it and bind it into memory once and which might give some performance gain since you are not changing the state of the GPU (depending on the API you're using).

A downside is reduced flexibility. Imagine having 1 texture that (including mesh and other data) fills up 1GB of VRAM, and that this texture contains all texture data for all objects that are drawn in a specific scene. Running this scene on a GPU with 1GB of VRAM will theoretically be possible.

If we later want to draw another scene that adds a mesh to the memory, we have suddenly exceeded our memory limit. To solve this problem we can remove stuff from memory that isn't being used. Unfortunately we wont be able to remove the giant texture from memory since it is used by all objects that are drawn.

Loading and removing from memory and changing the state of the GPU (binding and unbinding textures) has an overhead cost which is why you want to combine textures as much as possible.

To calculate the optimal size of your textures is highly dependent on your game and the system it is running on.

\$\endgroup\$
  • \$\begingroup\$ The biggest gain from using bigger textures is ability to reduce texture switches and you didn't write about that. Also I fail to see how loading textures into VRAM is faster with bigger textures. \$\endgroup\$ – Sopel Aug 31 '17 at 17:05
  • \$\begingroup\$ I never wrote that the actual loading is faster but that there might be a possibility for faster reads of the data. Edited the answer to be more clear. \$\endgroup\$ – George Hanna Sep 1 '17 at 7:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.