Sign in to follow this  

Textures: Power of 2 and Maximum Size

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

Hi, I'm new to 3D-Coding but tried some things out which led me to the following questions regarding texture sizes: 1.) In some books they say that textures should be powers of 2 (128x128, 64x64 and so on) since they wouldn't run on some Hardware otherwise. Is this still applicable today or is all Hardware on the market ready to work with textures which aren't powers of 2? And if it should be necessary what do I do exactly to achieve textures which aren't powers of 2? 2.) I read that maximum texture sizes are a problem and I shouldn't use them over 1024x786. Is this true and if yes how can I use big textures then? Thanks in advance.

Share this post


Link to post
Share on other sites
1) Non-power of two textures are supported in some drivers for newer hardware, yet most people still use power of two textures, because it is not as large of an inconvinience as it may sound. Just because the texture is a power of two does not mean that the entire texture must be drawn in each pass, as you learn more you'll learn about TexCoords which can control the portion of a texture which is drawn.

2) large textures do use a lot of memory, and video memory is a finite resource, the max texture sizes can be obtained via your API of choice, but it is rare to need textures that large in typical development. This too is only a minor setback since it is possible to split up your large image(s) into multiple textures.

(edit: sorry about the API of choice thing, I didn't realize that this was the DirectX forum, I believe in Direct3D 9 you want the MaxTextureWidth/MaxTextureHeight members of the D3DCAPS9 structure)

Share this post


Link to post
Share on other sites
During load, D3DX will scale your textures automatically.
Loading might fail if the texture is too big, though.

Textures don't need to have square dimensions, as long as width and height are powers of two and the aspect ratio isn't too extreme (e.g. 512x32). D3DCAPS9 contain information about max. texture size, non-rectangular textures and maximum texture ratios.

Share this post


Link to post
Share on other sites
Thanks.

Square dimensions are no necessity? That's nice to hear. :)

But my problem isn't really to get the information but how to use it. You said, that loading might fail and it's no option to cancel the game if I want to give it away and the hardware of the user can't handle it.

So it seems I have no chance but to do something against big textures and somehow cut and paste part of the textures so that they aren't bigger than the worst graphics card at the moment can handle.

But I have no idea how?!?

Share this post


Link to post
Share on other sites
One way to get around this problem is to use scaled textures.
For example most cards (read: all newer cards) are fine with 1024x1024 textures. For a 1280x1024 startup screen you can scale your picture with Photoshop/Paint Shop Pro using a nice filter and simply draw a textured quad the size of the game screen. The texture will look very good in lower resolutions (such as 1024x768) and resonably well in higher resolutions, too.

If you really need even larger textures, you can simply split the large image into several smaller ones (though I can't imagine why you would need something bigger than 1024x0124 [rolleyes]).

As for the non-squared textures: ratios that do not exceed 4:1 or 1:4 are unlikely to cause problems. Even if the driver does not support them, D3DX will scale these textures such that the driver is fine with them.

Can you provide some details on your texture requirements?
I simply cnnot think of a case where you need textures that are this large.


Pat

Share this post


Link to post
Share on other sites
It's kind of strange that you want to create a application that will use very hi-res textures and are worried that it won't run on older hardware. Thik of it this way: If your creating a state-of-the-art game and have really good graphics you can't expect it to run on a system that has a gfx card witch can't handle at least 1024x1024 textures anyway.

Share this post


Link to post
Share on other sites
Thanks for all the helpfull commands so far.

What I want to do is:

I want to give the user the ability to load every image he wants and display it in my app. So I assume many user will try to load very big pictures and I want to allow this. Further I want that it runs on old hardware even if it will slow done very much.

In fact the idea with the texture splitting sounds very reasonable but I have no idea how to do it.

Any advice would be wonderful.

Thanks in advance (again) :)

Share this post


Link to post
Share on other sites
Splitting works as follows:

Step 1)
Load image into surface:

LPDIRECT3DSURFACE9 pSurface;
D3DXIMAGE_INFO info;

// get image information
if ( FAILED ( D3DXGetImageInfoFromFile ( szFileName, &info ) ) )
{
return E_FAIL;
}

// create temporary surface
if ( FAILED ( m_pID3DDevice->CreateImageSurface ( info.Width, info.Height, d3dFormat, &pSurface ) ) )
{
return E_FAIL;
}

// try to load image into surface
HRESULT eResult = D3DXLoadSurfaceFromFile( pSurface, 0, 0, szFileName, 0, D3DX_FILTER_NONE, 0, 0 );

if ( FAILED(eResult) )
{
pSurface->Release ( );
return E_FAIL;
}




Step 2)
Create textures to split into:

// for simplicity I will use 128x128 tiles
int tilesX = info.Width / 128 + ((info.Width & 127) ? 1 : 0);
int tilesY = info.Height / 128 + ((info.Height & 127) ? 1 : 0);
int tileCount = tilesX * tilesY;

LPDIRECT3DTEXTURE9 *m_pTexture = new LPDIRECT3DTEXTURE8[tilesX * tilesY];
ZeroMemory(m_pTexture, tileCount * sizeof(LPDIRECT3DTEXTURE9));

for (int i = 0; i < tileCount; ++i) {
if ( FAILED ( D3DXCreateTexture ( m_pID3DDevice, 128, 128, 1, 0, d3dFormat, D3DPOOL_MANAGED, m_pTexture + i ) ) ) {
// delete all textures
for (int j = 0; j < tileCount; ++j) if (m_pTexture[j] != NULL) m_pTexture[j]->Release();
pSurface->Release();
return E_FAIL;
}
}




And finally step 3)
Populate textures:

// for simplicity's sake, no error checking here :)
int index = 0;
RECT rSourceRect, rDestRect;
rDestRect.left = rDestRect.top = 0;
for (int y = 0; y < tilesY; ++y) {
// setup source and destination regions
rSourceRect.top = y * 128;
rSourceRect.bottom = min(rSourceRect.top + 128, info.Height);
rDestRect.bottom = rSourceRect.bottom - rSourceRect.top;
for (int x = 0; x < tilesX; ++x, ++index) {

// setup source and destination regions
rDestRect.left = x * 128;
rDestRect.right = min(rDestRect.left + 128, info.Width);
rSourceRect.right = rDestRect.right - rDestRect.left;

LPDIRECT3DTEXTURE9 textureSurface;
// try to get the texture surface
m_pTexture[index]->GetSurfaceLevel(0, &textureSurface);
// load the tile from the large image
D3DXLoadSurfaceFromSurface(textureSurface, NULL, &rDestRect, pSurface, NULL, &rSourceRect, D3DX_FILTER_NONE, 0);
// done with the surface - release it
textureSurface->Release();
}
}

// ready. release large image surface
pSurface->Release();



This is from top my head so there might be errors [wink]

Have fun and keep asking if something is unclear,
Pat.

Share this post


Link to post
Share on other sites

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