Direct3D8 Loading Textures from Files - Different Dimensions?

Started by
8 comments, last by deadimp 18 years, 10 months ago
Yep, I have another question. This time it is about loading Direct3D8 textures from files. I'm using "D3DXLoadSurfaceFromFile" to load a surface from a file, and then blitting the surface to a texture (as in the tutorial Dissecting Sprites in Direct3D) with rectangles. However, when I get the texture's description using IDirect3DTexture8::GetLevelDesc(), the width returned, but not the height, is greater than the original source's width. I have a 105x15 pixel bitmap, yet when I load it, it says it is 128x15... Is this because of the whole "It needs to be a power of 2" controversy? If so, then is the bitmap's data "stretched" proportionally across the texture? And if it is, how would I convert coordinates of the original image to coordinates of the new image? The reason I'm asking is that I am accessing only parts of the texture and drawing them, and I have to define frame width and height in pixels, which would obviously change if the surface is padded (or can it be "stripped" if the power of two is closer?). However, when I do this, I get a distored image (an image that should be 15px is 13px wide instead). NOTE: I am using textured quads.
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
Advertisement
If you specify FILTER_NONE to D3DX, the texture will not be stretched to match the new dimensions of the image. You'll need to ensure your vertex UVs U element doesn't exceed (105/128.0f), and that you don't expect texture wrapping to work.

If you do specify a filter, the image will be stretched.
Grrr. Please GD.Net staff, fix the anonymous posting thing. It's really annoying.
Is there an easy way to retrieve the dimensions of the image before D3DX stretches it? I can do the rest of the calculations from there.
Well, actually, I have one more question... By not stretching, you do mean that it won't fill in the padded bytes, right? Something like this:
Original: 6x3 Bitmap; Output: 8x3 Bitmap (padded)           [P P]0 1 2 3 4 5 6 71 X X X X X 0 02 X X X X X 0 0

Where P denotes a padded pixel, X denotes a filled pixel, 0 denotes an empty space.
Is that right?
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
I think the optional srcInfo (from the D3DXLoadSurfaceFromFile / D3DXCreateTextureFromFile) is the dimensions and format of the image on disk. If you need to format and size of the image after loading you need to GetDesc(). There is also D3DXGetImageInfoFromFile() if the srcInfo doesn't work for you.

edit: Yeah, the padded space will be there, but be transparent black or some fixed color. You original image will be untouched in the upperleft corner of the surface.
Ah, thanks.
EDIT: Sorry, but I have one more question. Is there any size limit on textures? I tried loading 3712x58px image, but it gave me an invalid call error when I tried to blit the surface to the texture.
EDIT (again): Yeah, the basic framing stuff works now. Basically. Thanks again.

[Edited by - deadimp on June 15, 2005 6:24:36 PM]
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
The texture size limits vary by card. Get the device caps to find what is supported. These days ATI tend to be limited to 2Kx2K, while nVidia supports 4Kx4K. Going all the way back to the Rage pro (1998) we've had support for 1Kx1K. If you're aiming for anything vaguely modern, 2Kx2K should be fine as an upper limit.

Most large textures are only useful for 8 bit formats like P8, L8, or A8, as they eat up memory pretty quick. 4K*4K*32bit = 67,108,864 bytes (or 64MB). Then * 1.33 for mips and you're looking at 89,254,789 bytes (85MB or so) for a single texture. Textures like these just aren't very common.
Well, all I really need is something to contain a whole bunch of sprite images, but from what I've read, IDirect3D8Device::SetTexture() should be called as least times possible, so that's why I'm trying to contain it into one texture. Should I shift some of the images so instead of having 3712x58, I'd have something like 1856x116, or, to go even further, 928x232 (close to 1024)? Or should I simply have an array of textures for that sprite? I don't know why, but I don't really like the prospect of having to use multiple textures, if I were to draw multiple frames of the sprite in one section (therefore having to call SetTexture() multiple times). Do I have any valid reasoning behind this?
EDIT: Also, wouldn't it consume less memory to simply have one larger image than having many small images?
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
Keeping the number of textures down is best, yes. Since your image is only large in one dimension, it shouldn't eat up RAM too quickly.

A 928x232 image will get padded out to 1024x256, and will work on the largest variety of cards, as it needs to lowest texture resolution. It will probably be easiest to work with in whatever paint package you're using too. The 1856x116 will likely be fine on most cards. Unless you're targetting really old hardware, the choice is really all about your preference.

Yes, you want to use as few textures as possible. There are a variety of savings from using as few images as possible.

1) Image overhead. There are headers, start address alignment issues, etc that may take quite a bit of space per image that are hidden from you by D3D and the driver.

2) Image padding overhead. If you're not making your images pow2 sizes, each seperate image would require padding. Depending on the image sizes, this can add up quickly. If you use one texture, you'll have some waste from padding, but it should be minimal, and it's much easier to make use of this wasted space by simply putting in more images.

3) Drawing overhead. SetTexture will take lots of time. For a single animated sprite it doesn't matter, as it will be one SetTexture each frame. When you have multiple characters, you can reduce SetTexture calls. When drawing tiled backgrounds, it's much better to be able to just draw it at once. Not only do you remove SetTexture calls, but Draw calls, which are also extremely expensive.

There are some disadvantages too.

1) Mip images may mix with adjacent tiles, producing incorrect colors.

2) Unless you have an ATI card with centroid sampling, and a shader trying to use it, multisampling may sample texels from adjacent tiles.

For a 2D tile based game, you often don't scale the images, or use AA, so non of the disadvantages apply.
Thanks for your help. (Rating++)
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire

This topic is closed to new replies.

Advertisement