Power of two sprites...?

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

Recommended Posts

I've got a 2D game that I'm in the process of developing at the moment and I'm trying to figure out whether I need to use power of two textures or not, so I've created a little application that looks at the card capabilities and let's me know whether the card supports non-power of two textures unconditionally, conditionally, or not at all.

I've tried this application out on all of my target platforms and they all support non-power of two textures, at least conditionally. So I've now tried to test it, so I've got 4 textures, 2 power of two, 2 non-power of two. And I'm using an ID3DXSprite to draw them (maybe these days I shouldn't be? - Been a while since I did extensive 2D engine work!). They all draw fine, however the non-power of two textures seem to be scaled somehow, not their "original" size. Yet I have no idea why!

If anyone's got any ideas, I'm all-ears!

Share on other sites
here is what i used to load my texture with (non power of two / does not matter)

 D3DXIMAGE_INFO d3dxImageInfo; D3DXCreateTextureFromFileEx( D3D9Device, L"..\\donut.bmp", 320, // I had to set width manually. D3DPOOL_DEFAULT works for textures but causes problems for D3DXSPRITE. 384, // I had to set height manually. D3DPOOL_DEFAULT works for textures but causes problems for D3DXSPRITE. 1, // Don't create mip-maps when you plan on using D3DXSPRITE. It throws off the pixel math for sprite animation. D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_COLORVALUE(0.0f, 0.0f, 0.0f, 1.0f), &d3dxImageInfo, NULL, &texture ); // Create our sprite... D3DXCreateSprite( D3D9Device, &sprite ); 

did that help ?

Share on other sites

here is what i used to load my texture with (non power of two / does not matter)

 D3DXIMAGE_INFO d3dxImageInfo; D3DXCreateTextureFromFileEx( D3D9Device, L"..\\donut.bmp", 320, // I had to set width manually. D3DPOOL_DEFAULT works for textures but causes problems for D3DXSPRITE. 384, // I had to set height manually. D3DPOOL_DEFAULT works for textures but causes problems for D3DXSPRITE. 1, // Don't create mip-maps when you plan on using D3DXSPRITE. It throws off the pixel math for sprite animation. D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_COLORVALUE(0.0f, 0.0f, 0.0f, 1.0f), &d3dxImageInfo, NULL, &texture ); // Create our sprite... D3DXCreateSprite( D3D9Device, &sprite ); 

did that help ?

well, it helped me at least. (not with what I'm doing right now though) but I didn't know directx had a D3DXCreateSprite. I can go to bed now, because I learned something new. Thanks

Share on other sites
I'm now using the following settings:

 D3DXCreateTextureFromFileEx(d3ddev, L"ExampleNon.png", 220, 220, 1, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &exampleNon); 

Which seems to now display the texture at the correct size, but I have had to specify the texture sizes manually to get it to work. This seems like a bit of headache to say the least! As every time I update the graphics I may need to change the CreateTexture params, and thus re-compile the game. :S

Share on other sites

I'm now using the following settings:

 D3DXCreateTextureFromFileEx(d3ddev, L"ExampleNon.png", 220, 220, 1, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &exampleNon); 

Which seems to now display the texture at the correct size, but I have had to specify the texture sizes manually to get it to work. This seems like a bit of headache to say the least! As every time I update the graphics I may need to change the CreateTexture params, and thus re-compile the game. :S

no you do not need to do that, use this to parse a text file that contains your image info

 int numberofframes = 1; float width = 1; float height = 1; float fsx = 1; float fsy = 1; float alpha = 0; wstring ws; char *buf = new char[20]; memset(buf, 0, 20); fstream fs(Path); if(!fs) { // failed to open file / create stream } fs.getline(buf, 20, '\t'); // read till a TAB space is found width = (float)atof(buf); // width fs.getline(buf, 20, '\n');// read till a endofline is found height = (float)atof(buf); // height fs.getline(buf, 20, '\t');// read till a TAB space is found fsx = (float)atof(buf); // frame size x fs.getline(buf, 20, '\n');// read till a endofline is found fsy = (float)atof(buf); // frame size y fs.getline(buf, 20, '\n');// read till a endofline is found numberofframes = (int)atof(buf); // number of frames fs.getline(buf, 20, '\n');// read till a endofline is found alpha = (float)atof(buf); // alpha fs.getline(buf, 20, '\n'); string s; s.append(mediafolder); s.append(buf); ws.append(s.begin(), s.end()); // path to sprite sheet delete []buf; 

does that make sense ?

Share on other sites
Yeah I get that, however I've got 450MB~ of textures to load into 128MBs of VRAM. Obviously I need to cut it down so I'm looking at ways in which I can do it, SpriteSheets, non-power two textures, DDD / DXT Compression, etc.

Spritesheets didn't seem to help much, as I have a lot of animations that can't really be made into a spritesheet; only 1 frame will ever be drawn on screen at one time, so with a spritesheet I'm loading all the other frames into VRAM and wasting space they are using, making the card swap these large spritesheets in/out of VRAM every frame.

Share on other sites
To get the width and height of the image you don't have to read it from the file by yourself.
In D3D9 you can just use D3DXGetImageInfoFromFile;

 D3DXIMAGE_INFO ImageInfo; D3DXGetImageInfoFromFile(L"Example.png", &ImageInfo); Width = ImageInfo.Width; Height = ImageInfo.Height; 

Share on other sites

To get the width and height of the image you don't have to read it from the file by yourself.
In D3D9 you can just use D3DXGetImageInfoFromFile;

 D3DXIMAGE_INFO ImageInfo; D3DXGetImageInfoFromFile(L"Example.png", &ImageInfo); Width = ImageInfo.Width; Height = ImageInfo.Height; 

Fantastic, now that's what I'm talking about!

Share on other sites

Well it's kinda one OR the other.. as DXT compression isn't supported for non-power of two textures. So I don't know which will give the biggest benefit in terms of memory usage, but non-power of two will certainly retain quality better.

Share on other sites
the DX Docs say that dds can be easyaly converted to other formates or depths etc,
what you could try is to make it a power of 2 but only use certain parts of it, that way compression is used.

Share on other sites

the DX Docs say that dds can be easyaly converted to other formates or depths etc,
what you could try is to make it a power of 2 but only use certain parts of it, that way compression is used.

As I said earlier, spritesheets (or multiple textures in one file) don't seem to provide us with much benefit (having tested various methods, packing techniques, etc.).

Share on other sites
DDS is supported for non-power-of-2; the constraint is that the dimensions must be multiples of 4 (as it compresses a 4x4 block of the source), which also imples that they must be at least 4.

Share on other sites
If you look at the documentation for D3DXCreateTextureFromFileEx you'll find:

Width in pixels. If this value is zero or D3DX_DEFAULT, the dimensions are taken from the file and rounded up to a power of two. If the device supports non-power of 2 textures and D3DX_DEFAULT_NONPOW2 is specified, the size will not be rounded.[/quote]