Page 1 of 1

Specify maximum texture size?

Posted: Thu Aug 04, 2011 6:20 am
by pepeshka
I'm noticing as I load more and more meshes into my app that I'm eating up a lot more memory than I intended; looking over the meshes I've created, it looks like I'm using too many high-resolution images for textures.

Rather than go through every mesh I've created and scale down the textures, I'm hoping to be able to scale those down at runtime. I first tried to write a method to load the textures from the video driver, scale them, and resave them...this worked to a degree, but I keep getting access violation exceptions (it looks like some materials on my models don't point to textures, or something, I haven't really hammered this out yet - I get exceptions when trying to use the texture from the material at all).

I'm hoping there is some built-in way to specify a global (or mesh-by-mesh, or even material-by-material) maximum texture size, and have textures scale automatically. I'm aware the video driver can tell me what the max supported size is, but I'm hoping to have some control over that maximum. Any ideas?

Re: Specify maximum texture size?

Posted: Thu Aug 04, 2011 9:58 pm
by Lonesome Ducky
You could create your own function that, when called, goes through all textures loaded and scales them down if necessary. This would be after loading your textures, of course.

Re: Specify maximum texture size?

Posted: Fri Aug 05, 2011 7:49 am
by hendu
Q3 did it before loading the textures (loading as in sending to the driver).

Re: Specify maximum texture size?

Posted: Fri Aug 05, 2011 12:39 pm
by hybrid
Yeah, you should definitely do this before loading it to the driver. Otherwise the texture size is not easily changeable, and you have to scale your texture coords etc. If you don't do automatic loading via meshes, you can load your texture into an IImage first, and scale that into the texture. But setting a fixed size for automated loading is not available (and also not on the TODO so far). Don't know if it's really that useful.

Re: Specify maximum texture size?

Posted: Fri Aug 05, 2011 1:07 pm
by Lonesome Ducky
hybrid wrote:Yeah, you should definitely do this before loading it to the driver. Otherwise the texture size is not easily changeable, and you have to scale your texture coords etc. If you don't do automatic loading via meshes, you can load your texture into an IImage first, and scale that into the texture. But setting a fixed size for automated loading is not available (and also not on the TODO so far). Don't know if it's really that useful.
Wouldn't the texture coords still be ok? They'd be in the 0-1 range, so wouldn't they still fit the smaller texture?

Re: Specify maximum texture size?

Posted: Fri Aug 05, 2011 3:37 pm
by hybrid
Well, you cannot make a texture smaller after creation. So if you scale the texture down, it would only cover a part of the whole texture. So texture coords have to be smaller than 1. And it would only work for non-repeated ones. Moreover, it eats up the same gfx memory, so no win at all. Texture have to be scaled before or duting upload, but the size have to be correct ahead.

Re: Specify maximum texture size?

Posted: Fri Aug 05, 2011 6:20 pm
by Acki
Lonesome Ducky wrote:Wouldn't the texture coords still be ok? They'd be in the 0-1 range, so wouldn't they still fit the smaller texture?
of course they will work, that's why the value is between 0 and 1 (see it like a percentage value not as a position)... ;)

Re: Specify maximum texture size?

Posted: Sat Aug 06, 2011 6:48 pm
by pepeshka
Thanks for the help all! This is what I've come up with (mostly cribbed off of other posts on the forum):

Code: Select all

void RescaleTexture(irr::scene::IMesh* inputMesh, irr::core::dimension2di targetSize)
{
        video::IVideoDriver* vidDriver = smgr->getVideoDriver();
 
        for (int i = 0; i < inputMesh->getMeshBufferCount(); i++)  //for each mesh in buffer,
        {
                        video::ITexture* inputTexture = inputMesh->getMeshBuffer(i)->getMaterial().getTexture(0);
                        video::SMaterial mat = inputMesh->getMeshBuffer(i)->getMaterial();
 
                        if (inputTexture != NULL && inputTexture->getSize().Height >0 && inputTexture->getSize().Width > 0)
                        {
 
                                irr::video::IImage * image = vidDriver->createImage(const_cast<irr::video::ITexture *>(inputTexture), irr::core::vector2di(0, 0), inputTexture->getSize() );
                                irr::video::IImage * transformedImage;
 
                                transformedImage = vidDriver->createImage(inputTexture->getColorFormat(), irr::core::dimension2d<irr::u32>(targetSize));
 
                                image->copyToScaling(transformedImage);
 
                                irr::io::path saved = inputTexture->getName();
                                vidDriver->removeTexture(inputTexture);
                                video::ITexture* toSet = vidDriver->addTexture(saved,  transformedImage);
                                inputMesh->getMeshBuffer(i)->getMaterial().setTexture(0, toSet);
 
                                image->drop();
                                transformedImage->drop();
                        }
        }
}
It's working for most of my models, and it's definately cutting down on my memory footprint (as reported in the task manager), but the problem is that using the inputTexture is sometimes causing an access violation exception. It looks like some materials on some models point to bad sections of memory? Am I screwing something up there?

I've also found that merging all the parts of my model into one mesh before exporting will resolve the problem for most of them, but I don't think I can do that for animated models.

Is there some way to detect these 'bad' materials and skip over them?

Re: Specify maximum texture size?

Posted: Wed Aug 10, 2011 2:23 am
by pepeshka
Actually I think my problem is in this line:

inputMesh->getMeshBuffer(i)->getMaterial().setTexture(0, toSet);

It looks like I'm getting a const Material, then trying to use a setter. I don't think the mesh's texture pointer is getting updated, so when it goes to render it's pointing off into some place in memory that I've removed.

How can I update the texture the material uses?