Page 1 of 1
[2.1] Reloading textures
Posted: Sun Mar 29, 2015 8:40 pm
by xrgo
Hello! I am trying to reload an object's texture:
Code: Select all
Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>(
subitem->getDatablock() );
datablock->getTexture(Ogre::PBSM_DIFFUSE)->reload();
but it just disappear, do I need to refresh something else?
Re: [2.1] Reloading textures
Posted: Sun Mar 29, 2015 11:18 pm
by dark_sylinc
I'm afraid it doesn't work that way. The TexturePtr is an old interface that is manually filled by the HlmsTextureManager. When you call reload it won't go through HlmsTextureManager (and even if it did, it would have no way to determine which texture in particular to reload).
There is no way to reload at the moment. The steps taken in HlmsTextureManager::createOrRetrieveTexture would have to be repeated but using an mTextureArrays[mapType] that already exists (the one that controls the texture).
What may work is to call HlmsTextureManager::destroyTexture and immediately call HlmsTextureManager::createOrRetrieveTexture (beware it might return a different pointer).
Re: [2.1] Reloading textures
Posted: Mon Mar 30, 2015 1:49 am
by xrgo
Thank you, that's good enough for me. This is my code for reloading a texture:
Code: Select all
Ogre::HlmsManager *hlmsManager = Ogre::Root::getSingletonPtr()->getHlmsManager();
Ogre::HlmsTextureManager *hlmsTextureManager = hlmsManager->getTextureManager();
hlmsTextureManager->destroyTexture("texture.dds");
Ogre::HlmsTextureManager::TextureLocation texLocation = hlmsTextureManager->createOrRetrieveTexture( "texture.dds", Ogre::HlmsTextureManager::TEXTURE_TYPE_DIFFUSE);
Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>( subitem->getDatablock() );
datablock->setTexture( Ogre::PBSM_DIFFUSE, texLocation.xIdx, texLocation.texture );
Re: [2.1] Reloading textures
Posted: Mon Mar 30, 2015 2:34 am
by xrgo
Now I have another problem. To reload the texture I need to know its file name, but if I do:
Code: Select all
Ogre::TextureManager::ResourceMapIterator textureResourceMapIterator = Ogre::TextureManager::getSingleton().getResourceIterator();
while (textureResourceMapIterator.hasMoreElements())
{
Ogre::ResourcePtr texturePtr = textureResourceMapIterator.getNext();
std::cout<<texturePtr->getName()<<std::endl;
}
I get names like
Code: Select all
[Hash 0xeb2bfd33]
[Hash 0xd84c7c3a]
[Hash 0x296098eb]
[Hash 0x594d701c]
[Hash 0xf16e7c5b]
[Hash 0x9b4ce5aa]
[Hash 0xa7121903]
HlmsTextureManager/0
HlmsTextureManager/1
HlmsTextureManager/2
HlmsTextureManager/3
HlmsTextureManager/4
HlmsTextureManager/5
HlmsTextureManager/6
HlmsTextureManager/7
HlmsTextureManager/8
HlmsTextureManager/9
HlmsTextureManager/10
HlmsTextureManager/11
HlmsTextureManager/12
HlmsTextureManager/13
rtt/140084109256816/[Hash 0x83fe644c]
I think the ones that has "HlmsTextureManager" are the ones that my item uses, but how do I translate this names to the file name, or where else can I get the file name??
If I try to get it from the datablock
datablock->getTexture(Ogre::PBSM_DIFFUSE)->getName()
its the same
Thanks in advance!
EDIT:
I am doing a semi-automated texture reload so I need to do one of this:
1. check for every texture in HlmsTextureManager if that file has changed. For that I need to know the file name
2. watch my textures directory, and when a texture file changed update the datablocks that are using this texture file. For this I have the texture file name, but I need to search which datablock is using it
Re: [2.1] Reloading textures
Posted: Mon Mar 30, 2015 4:14 am
by xrgo
any particular reason why in OgreHlmsTextureManager.cpp line ~506
this:
Code: Select all
textureArray.texture = TextureManager::getSingleton().createManual(
"HlmsTextureManager/" +
StringConverter::toString( mTextureId++ ),
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
texType, width, height, depth, numMipmaps - baseMipLevel,
defaultPixelFormat == PF_UNKNOWN ? imageFormat :
defaultPixelFormat,
TU_DEFAULT & ~TU_AUTOMIPMAP, 0,
mDefaultTextureParameters[mapType].hwGammaCorrection,
0, BLANKSTRING, false );
cant be this:
Code: Select all
textureArray.texture = TextureManager::getSingleton().createManual(
texName, //<<<<<<<<<< actual file name
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
texType, width, height, depth, numMipmaps - baseMipLevel,
defaultPixelFormat == PF_UNKNOWN ? imageFormat :
defaultPixelFormat,
TU_DEFAULT & ~TU_AUTOMIPMAP, 0,
mDefaultTextureParameters[mapType].hwGammaCorrection,
0, BLANKSTRING, false );
??? I did it and it solves my problem, but not sure if it breaks something
Re: [2.1] Reloading textures
Posted: Mon Mar 30, 2015 6:37 am
by dark_sylinc
xrgo wrote:any particular reason why in OgreHlmsTextureManager.cpp line ~506
Yes. Re-read the manual section about the HlmsTextureManager, then re-read my post again:
The TexturePtr is an old interface that is manually filled by the HlmsTextureManager
The TexturePtr may contain "tens of textures in the same texture". A lot of things can break if you assign a name of an actual texture to these automatically generated textures.
The TexturePtr doesn't have enough information to retrieve the name. You need the data in TextureLocation (basically the pointer & the xIdx for texture arrays, and the pointer, xIdx, yIdx & divisor for texture atlases) to get all the required information; and compare it to the entires in HlmsTextureManager::mTextureArrays until you find a match (there is not a function to do this for you although this would be trivial to do).
Re: [2.1] Reloading textures
Posted: Wed Apr 01, 2015 1:04 am
by xrgo
dark_sylinc wrote:The TexturePtr may contain "tens of textures in the same texture"
Doh, I alwaays knew that, I dont know what I was thinking xD.
I finally solved my problem like this:
Since I am creating all my materials by code, I save the hlms texture name that my texture is located in a map:
Code: Select all
Ogre::HlmsTextureManager::TextureLocation texLocation = hlmsTextureManager->createOrRetrieveTexture( fileName, Ogre::HlmsTextureManager::TEXTURE_TYPE_MONOCHROME);
datablock->setTexture( Ogre::PBSM_DIFFUSE, texLocation.xIdx, texLocation.texture );
textureName[fileName] = texLocation.texture->getName();
so later I can refresh my Item's datablock:
Code: Select all
Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>( Item->getSubItem(0)->getDatablock() );
if( !datablock->getTexture(Ogre::PBSM_DIFFUSE).isNull() &&
datablock->getTexture(Ogre::PBSM_DIFFUSE)->getName() == textureName.at(textureFileName) ){
hlmsTextureManager->destroyTexture(textureFileName);
Ogre::HlmsTextureManager::TextureLocation texLocation texLocation = hlmsTextureManager->createOrRetrieveTexture( textureFileName, Ogre::HlmsTextureManager::TEXTURE_TYPE_DIFFUSE);
datablock->setTexture( Ogre::PBSM_DIFFUSE, texLocation.xIdx, texLocation.texture );
textureName[textureFileName] = texLocation.texture->getName()); //update texture name
}
Thank you very much!!
Re: [2.1] Reloading textures
Posted: Wed May 13, 2015 1:25 am
by darkheron
I am bumping this up because in the course of my own foray into reloading textures, I have come across what I believe to be a bug.
In HlmsTextureManager.cpp line 596 inside of the void HlmsTextureManager::destroyTexture( IdString aliasName ) method specifically this section of code
Code: Select all
void HlmsTextureManager::destroyTexture( IdString aliasName )
{
TextureEntry searchName( aliasName );
TextureEntryVec::iterator it = std::lower_bound( mEntries.begin(), mEntries.end(), searchName );
if( it != mEntries.end() && it->name == searchName.name )
{
mEntries.erase( it ); <--------------------- THIS INVALIDATES THE ITERATOR it
TextureArrayVec::iterator texArrayIt = mTextureArrays[it->mapType].begin() + it->arrayIdx; <--- BUT STILL WE USE IT
texArrayIt->destroyEntry( it->entryIdx ); <----------- AND AGAIN
if( texArrayIt->activeEntries == texArrayIt->maxTextures )
{
//The whole array has no actual content. Destroy the texture.
ResourcePtr texResource = texArrayIt->texture;
TextureManager::getSingleton().remove( texResource );
texArrayIt = efficientVectorRemove( mTextureArrays[it->mapType], texArrayIt ); <-------- AND AGAIN
if( texArrayIt != mTextureArrays[it->mapType].end() ) <-------------- AND AGAIN
{
//The last element has now a new index. Update the references in mEntries
size_t newArrayIdx = it->arrayIdx; <--------------------- YEP, AGAIN :)
StringVector::const_iterator itor = texArrayIt->entries.begin();
StringVector::const_iterator end = texArrayIt->entries.end();
while( itor != end )
{
searchName.name = *itor;
it = std::lower_bound( mEntries.begin(), mEntries.end(), searchName );
assert( it != mEntries.end() && it->name == searchName.name );
it->arrayIdx = newArrayIdx;
++itor;
}
}
}
}
}
Specifically, when destroying a texture, the operation would work correctly once, but then because there is trash inside of the value pointed to by the entity iterator, the cleanup fails, (as evidenced by data dump from pHlmsTextureManager->dumpMemoryUsage();) and a subsequent destroyTexture operation will cause an abortion. By simply caching the values we need into local variables like so :
Code: Select all
uint16 arrayIdx = it->arrayIdx;
uint16 entryIdx = it->entryIdx;
TextureMapType mapType = it->mapType;
mEntries.erase( it );
and using the locals in place of the derefrenced iterator, everthing seems to work excellent, and I can reload my textures at runtime ad nauseam with no error, and a perfect HlmsTextureManager memory dump.
I believe this is a bug, but I thought I should raise the issue here to be sure.
Re: [2.1] Reloading textures
Posted: Wed May 13, 2015 2:49 am
by dark_sylinc
Fixed. Thanks. It was a serious bug (To be honest... I must've been high when I wrote that, I can't believe I wrote that buggy abomination).
Wasn't the only thing failing if you look at the
commit!
Cheers and thanks,
Matias
Re: [2.1] Reloading textures
Posted: Wed May 13, 2015 1:00 pm
by darkheron
patched up, but now on a deletion the assert at line 619:
Code: Select all
assert( itEntry != mEntries.end() && itEntry->name == searchName.name );
Triggers. A quick run through the debugger seems to suggest that the StringVector iterator itor will eventually return a NULL string, since there are actually more entries in the vector then are actually used, so itEntry->name != seachName.name. Maybe you mean to iterate from 0..texArrayIt->activeEntries here?
Just a heads up. I can dig into it more later if you like, but for now it's off to work.
Re: [2.1] Reloading textures
Posted: Wed May 13, 2015 6:32 pm
by dark_sylinc
My subconscious kept telling me there was still a bug there! Thanks!
Hopefully,
it's fixed for good this time.
Re: [2.1] Reloading textures
Posted: Sun May 17, 2015 9:16 pm
by xrgo
another (maybe) related question:
How can I resize a texture? or load it scaled or something like that. What I need:
I have some really big textures (4k) and I want to be able to reduce the size, for instance to 512 to be able to run my app in graphics cards with little VRAM.
Is that possible? I know I can have "duplicated" files with lower resolution, but would be great if I could o it by code.
Thanks!
Re: [2.1] Reloading textures
Posted: Sun May 17, 2015 9:24 pm
by dark_sylinc
The HlmsTextureManager will already try to downscale the texture when looking at RenderSystemCapabilities::getMaximumResolutionXD (where X is a number).
Though what you're saying is about downscaling due to VRAM limits, rather than texture resolution ones. But the code should be the same.
Note however this feature hasn't been thoroughly tested. I've ran into a few crashes on some textures that I didn't check worry too much at the time. You may want to try it for yourself by artificially changing the maximum resolution or slightly changing OGRE's code.
Re: [2.1] Reloading textures
Posted: Mon May 18, 2015 4:50 pm
by xrgo
dark_sylinc wrote:The HlmsTextureManager will already try to downscale the texture when looking at RenderSystemCapabilities::getMaximumResolutionXD (where X is a number).
Thank you, I tried forcing a max res in the HlmsTextureManager and it worked, but now I want to do it inside my code, I tried setting up a custom RenderSystemCapabilities, but I am having some trouble.
If I do this:
Code: Select all
Ogre::RenderSystemCapabilities *caps = renderSys->createRenderSystemCapabilities();
before creating my windows it crashes at that line, but if I do it after I get an error here:
Code: Select all
renderSys->useCustomRenderSystemCapabilities(caps);
this error:
Code: Select all
Custom render capabilities must be set before the RenderSystem is initialised
any ideas?
Re: [2.1] Reloading textures
Posted: Wed May 27, 2015 2:36 pm
by xrgo
any ideas why customRenderSystemCapabilities is not working?
Re: [2.1] Reloading textures
Posted: Thu May 28, 2015 5:15 am
by xrgo
Hello, I came up with a solution that I like a lot! I noticed that samplerBlocks had a "mMinLod" and if I set any number but 0, like 4, I do get lower resolution textures! but no memory consumption decrease =(
So I take that idea an modified the method "createOrRetrieveTexture" a little to accept a last parameter "minLod":
Code: Select all
TextureLocation createOrRetrieveTexture( const String &texName, TextureMapType mapType, float minLod=0 );
so then after it sees if it needs to resize the texture (around line 425) I do:
Code: Select all
............
width = static_cast<uint>( floorf( maxResolution * aspectRatio ) );
height = maxResolution;
}
image.resize( width, height );
}
}
//New resize!! when asked
if( minLod!=0 ){
baseMipLevel = 0;
while( baseMipLevel < minLod
&& (baseMipLevel <= image.getNumMipmaps()) )
{
width >>= 1;
height >>= 1;
++baseMipLevel;
}
}
//Find an array where we can put it. If there is none, we'll have have to create a new one
TextureArrayVec::iterator dstArrayIt = findSuitableArray( mapType, width, height, depth,
faces, imageFormat,
numMipmaps - baseMipLevel );
.........
Using this method I do get lower resolution textures and lower the memory usage!!! and I can choose the kind of texture, or which texture I want to reduce quality =)
For example now in my app I have a quality selector: in "High" texture memory usage is like 1.5gb, and in "Low" is like 0.5gb.
The only problem is that it needs mipmaps, but all my textures already have it so not an issue for me
Is there any chances something like this gets implemented in to Ogre?
Thanks!!
Re: [2.1] Reloading textures
Posted: Thu May 28, 2015 7:14 am
by dark_sylinc
xrgo wrote:For example now in my app I have a quality selector: in "High" texture memory usage is like 1.5gb, and in "Low" is like 0.5gb.
The only problem is that it needs mipmaps, but all my textures already have it so not an issue for me
Is there any chances something like this gets implemented in to Ogre?
Thanks!!
Call image.generateMipmaps; but beware it won't work with all formats (e.g. compressed formats). Returns false if mipmaps weren't generated. Also previous mipmaps will be discarded (e.g. if already embedded in the file)
The idea is quite clever btw. I was thinking of something similar, but I like yours better.
Re: [2.1] Reloading textures
Posted: Wed Jun 24, 2015 7:37 pm
by xrgo
dark_sylinc wrote:The idea is quite clever btw. I was thinking of something similar, but I like yours better.
Any chances to see this (or similar) integrated with Ogre??
And another related topic:
lurking some information on another forums I found this: (
http://www.gamedev.net/topic/669411-wha ... try5236291)
and I liked this Idea very much:
Stainless wrote:One trick I use a lot is to record the highest mipmap ever used on a texture. It's complicated to get the detection to work, but it can be done. Then I can generate a report and flag any large textures that are never used at full resolution.
Is something like this possible in Ogre 2.1? I dont need it now, but I think is very interesting and useful
Thanks!
Re: [2.1] Reloading textures
Posted: Thu Jun 25, 2015 8:26 am
by Zonder
xrgo wrote:dark_sylinc wrote:
Stainless wrote:One trick I use a lot is to record the highest mipmap ever used on a texture. It's complicated to get the detection to work, but it can be done. Then I can generate a report and flag any large textures that are never used at full resolution.
Is something like this possible in Ogre 2.1? I dont need it now, but I think is very interesting and useful
Thanks!
+1