Why are textures always square powers of two? What if they aren't?

From:http://gamedev.stackexchange.com/questions/26187/why-are-textures-always-square-powers-of-two-what-if-they-arent

Why are the resolution of textures in games always a power of two (128x128, 256x256, 512x512, 1024x1024, etc.)? Wouldn't it be smart to save on the game's file size and make the texture exactly fit the UV unwrapped model?

What would happen if there was a texture that was not a power of two?

Would it be incorrect to have a texture be something like 256x512, or 512x1024? Or would this cause the problems that non-power-of-two textures may cause?

Answers:

--------------------------------------------------------------------------------------------------------------------------------------------

Why are the resolution of textures in games always a power of two (128x128, 256x256, 512x512, 1024x1024, etc.)?

As Byte56 implied, the "power of two" size restrictions are (were) that each dimension must be, independently, a power of two, not that textures must be square and have dimensions which are a power of two.

However, on modern cards and which modern graphics APIs, this "restriction" has been relaxed significantly such that textures dimensions can be, within reason, just about anything you like. However:

Wouldn't it be smart to save on the game's file size and make the texture exactly fit the UV unwrapped model? What would happen if there was a texture that was not a power of two?

By ensuring the texture dimensions are a power of two, the graphics pipeline can take advantage of optimizations related to efficiencies in working with powers of two. For example, it can be (and absolutely was several years back before we had dedicated GPUs and extremely clever optimizing compilers) faster to divide and multiply by powers of two. Working in powers of two also simplified operations within the pipeline, such as computation and usage of mipmaps (a number that is a power of two will always divide evenly in half, which means you don't have to deal with scenarios where you must round your mipmap dimensions up or down).

It's true you "waste" some space this way, but the extra space is usually worth it for the tradeoff in render performance. Additionally there are techniques, such as compression or packing multiple images into a single texture space that can alleviate some of the storage waste.

--------------------------------------------------------------------------------------------------------------------------------------------

Why are textures always square powers of two?

Textures are not always square nor are they always powers of two. The reason why they tend to bepowers of two is usually to increase compatibility with older video cards that imposed that restriction. As for non-square textures, that's not usually a problem. To summarize:

  • Textures typically don't need to be square - although DirectX does have a D3DPTEXTURECAPS_SQUAREONLY capability but I've worked with non square textures even in older hardware with no problems.
  • Textures should be powers of two because many older graphical cards still require it. The reason for that restriction was so that they could perform some optimizations to the texture mapping operations. Most modern graphic cards don't have this restriction either.

--------------------------------------------------------------------------------------------------------------------------------------------

It relates to graphics card optimizations. They've been designed to process them in that way. Most cards these days will allow you to load textures with dimensions that are not powers of two, but it will likely have a negative impact on performance. There is a good chance that when it loads it is actually going to be converted costing you load time and not saving any memory. Non-square textures are generally OK, as long as both their dimensions are powers of two.

One way of dealing with odd size textures is using a Texture Atlas. Basically, you place multiple textures together into a single texture and use the texture coordinates of your vertices to reference the particular image you need. This comes with additional performance benefits as well, because it allows to avoid state changes. A common use of this is placing all of the elements of the interface into a single texture, meaning that if you have batched up your interfaces vertices into a single buffer object, you can draw the whole thing with a single call, rather than switching textures many times and making a separate draw call for each one.

--------------------------------------------------------------------------------------------------------------------------------------------

The problem is that some hardware has limited support for textures that don't have power of two dimensions.

For example, look at the bottom of http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876%28v=vs.85%29.aspx and read footnotes 3 and 4 there.

3 At feature levels 9_1, 9_2 and 9_3, the display device supports the use of 2-D textures with dimensions that are not powers of two under two conditions. First, only one MIP-map level for each texture can be created, and second, no wrap sampler modes for textures are allowed (that is, the AddressU, AddressV, and AddressW members of D3D11_SAMPLER_DESC cannot be set to D3D11_TEXTURE_ADDRESS_WRAP).

4 At feature levels 10_0, 10_1 and 11_0, the display device unconditionally supports the use of 2-D textures with dimensions that are not powers of two.

--------------------------------------------------------------------------------------------------------------------------------------------

Graphics hardware is optimized for matrix operations, fragment operations and vector operations. Simply put square matrices are easier to deal with, as calculations may be done in blocks( called fragments ), hardware is optimized for block operations, which is why there are things like file buffers, the RAM blit does not blit to disk until a block has been populated. The same is true of graphics memory.

The frame buffer is composed of fragments which are square. For example in a screen with a resolution 800x600 and an RGB color space (0-255) there are 800x600 points with 3 bytes each channel there are a grand total of 3x800x600 = 1,440,000 bytes to address in the frame buffer. That means there are 1,875 addressable fragments that are 256x256x3 bytes. Because the texture data is square it makes it significantly easier to map from the GRAM matrix to the screen buffer matrix using bicubic scaling, where as if it wasn't square the bias for the longer side would take more time to calculate when it needed to be scaled.

Many graphics APIs will accept non square texture data, because they accept UV mapping coordinates as floating point data, however once it is sent to the GPU, padding is added to the texture data, because the actual proportions of the image do not change the mapping appears unaffected, however padding is added to the texture data, because the GPU likes addressing it as a perfect square.

So if a 100x1024 image is used, and image that is 1024x1024 is used which means 946,176 bytes are wasted. Even more so if compositing is to be done, because an alpha channel will need to be added in order to indicate that the padding data should not effect the composited texture.

--------------------------------------------------------------------------------------------------------------------------------------------

Modern hardware can (finally) cope with enabling wrap modes on non-power of two based textures, however non-power of two textures still tend to waste GPU memory as they tend to get padded up along the width by some hardware specific amount (either to some tile size or rounded up to the next power of two size that contains the texture).

As this is hardware dependant and the vendors generally won't get into the specifics of these details, the safest thing to do is to continue to use power of two dimensions for textures, so as not to waste GPU ram.

posted @ 2015-03-20 11:43  Unikanade  阅读(274)  评论(0编辑  收藏  举报