Texture Reloading

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
DtD
Posts: 264
Joined: Mon Aug 11, 2008 7:05 am
Location: Kansas
Contact:

Texture Reloading

Post by DtD »

I've been implementing automatic resource reloading in our game, and went to expand it to reload textures. However, I had the problem that there is no good way to reload textures in Irrlicht. I could just remove the texture and get it again, but then I'd have to update any meshes, etc that are using it. My first idea was to reload the file as an IImage and then lock the texture and memcpy, but then there are annoying issues with resizing stuff that happens when NPOT textures are not supported blah blah blah.

So, I decided to mix and match the constructor and destructor of irr::video::C3D9Texture to make a reload function. I have plans to expand it to OpenGL and potentially the other drivers eventually. Also, I made this in about 30 minutes, so no guarantees on stability. I know almost for sure that it won't like it if you reload a texture loaded from an archive.

Here's the diff:

Code: Select all

diff -r 773c89d96480 include/ITexture.h
--- a/include/ITexture.h	Tue Mar 16 01:22:23 2010 -0500
+++ b/include/ITexture.h	Thu Apr 08 13:59:50 2010 -0500
@@ -158,6 +158,9 @@
 
 	//! Get name of texture (in most cases this is the filename)
 	const io::SNamedPath& getName() const { return NamedPath; }
+	
+	//!Reload the texture from disk
+	virtual void reload() {}
 
 protected:
 
diff -r 773c89d96480 source/Irrlicht/CD3D9Texture.cpp
--- a/source/Irrlicht/CD3D9Texture.cpp	Tue Mar 16 01:22:23 2010 -0500
+++ b/source/Irrlicht/CD3D9Texture.cpp	Thu Apr 08 13:59:50 2010 -0500
@@ -53,7 +53,7 @@
 			   u32 flags, const io::path& name, void* mipmapData)
 : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
 	TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN),
-	HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false)
+	HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false), creationFlags(flags)
 {
 	#ifdef _DEBUG
 	setDebugName("CD3D9Texture");
@@ -102,6 +102,49 @@
 		Device->Release();
 }
 
+//!Reload the texture from disk
+void CD3D9Texture::reload()
+{
+ //Pre-Creation
+ if (IsRenderTarget)
+ {
+  os::Printer::log("Can't reload a RTT!",ELL_WARNING);
+  return;
+ }
+ os::Printer::log("Reloading DIRECT3D9 Texture!");
+ 
+ IImage* image = Driver->createImageFromFile(NamedPath);
+ if (!image)
+ {
+  os::Printer::log("Could not reload the image!",ELL_ERROR);
+  return;
+ }
+ 
+ //Destruction
+ if (Texture) {Texture->Release();}
+ if (RTTSurface) {RTTSurface->Release();}
+ //Not sure if I need to do that depth buffer thing
+ if (Device) {Device->Release();}
+ 
+ //Creation
+ //We should be able to safely skip over 99% of the rubbish constructor init list stuff
+ Device = Driver->getExposedVideoData().D3D9.D3DDev9;
+ if (Device) {Device->AddRef();}
+ 
+ if (createTexture(creationFlags,image))
+ {
+  if (copyTexture(image))
+  {
+   regenerateMipMapLevels(0);
+  }
+ }
+ else
+ {
+  os::Printer::log("Could not recreate DIRECT3D9 Texture.", ELL_WARNING);
+ }
+ image->drop();
+}
+
 
 void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format)
 {
diff -r 773c89d96480 source/Irrlicht/CD3D9Texture.h
--- a/source/Irrlicht/CD3D9Texture.h	Tue Mar 16 01:22:23 2010 -0500
+++ b/source/Irrlicht/CD3D9Texture.h	Thu Apr 08 13:59:50 2010 -0500
@@ -74,6 +74,9 @@
 
 	//! Returns pointer to the render target surface
 	IDirect3DSurface9* getRenderTargetSurface();
+	
+	//!Reload the texture from disk
+	virtual void reload();
 
 private:
 	friend class CD3D9Driver;
@@ -114,6 +117,7 @@
 	bool HasMipMaps;
 	bool HardwareMipMaps;
 	bool IsRenderTarget;
+	irr::u32 creationFlags;
 };

Also, this is for Irrlicht 1.7 (Non SVN) the diff was made by our Mercurial repo we keep Irrlicht in.

~David
Mel
Competition winner
Posts: 2293
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

What would be the utility of something like this with a texture cache already implemented? the cache keeps track of the used textures, and the textures that are no longer needed and can be safely removed.

If a texture had to be reloaded (i.e. it was loaded, unloaded, and then loaded again), why not simply keep it in the cache?, perhaps, referencing it manually, and dropping it manually when it is no longer needed?

the utility to clear the cache, is capable of keeping the used -referenced- textures, and erasing the unused or unreferenced ones.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
DtD
Posts: 264
Joined: Mon Aug 11, 2008 7:05 am
Location: Kansas
Contact:

Post by DtD »

For our purposes, the texture is reloaded from the file when the texture is updated from an external program, this method of reloading it retains the texture's pointer (so meshes using it don't need to be updated.)

See the link to my blog post explaining it with our game's GUI in the first post.

~David
aanderse
Posts: 155
Joined: Sun Aug 10, 2008 2:02 pm
Location: Canada

Post by aanderse »

this is pretty amazing. if you had some #ifdef's in the code so this was only implemented in the development version of the game this would be so incredibly useful for people tweaking content, scripts, etc.... awesome work! i'll be watching this thread to see when you get it implemented for other drivers!
thanks for sharing this!
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Well there is an other "easy" way to go (short version):
seperate the hardwarebuffer and the softwarebuffer, shrink ITexture to a pure hardwarelink like the IMeshbuffer Stuff. If one wants to reload a Texture/reset the Device/change the driver, just drop the links. They will be recreated automatically on demand.
Or in other words: http://www.7bitfaster.de/downloads/irrl ... iative.pdf section 2.2.3 . But it is just an alternativ idea :) .
Mel
Competition winner
Posts: 2293
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Ah! i understand now. Great idea! :)
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply