Dynamic Texture Size Support

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
varmint
Posts: 46
Joined: Fri Oct 06, 2006 4:33 pm

Dynamic Texture Size Support

Post by varmint »

For our project we wanted to do all the textures in the highest detail. We made that 1024x1024 (were it made sense) . Scaling down is easy, scaling up isn't so. Then instead of creating multiple textures of different sizes and including them in the download thus increasing download size, I added a little code to IVideoDriver.h and CNullDriver.cpp

in IVideoDriver.h just after

Code: Select all

	class IMaterialRenderer;
	class IGPUProgrammingServices;
add

Code: Select all

	//dynamic texture size support
	enum IRR_TEXTURESIZEOPT
	{
		IRR_TEX_TINY,
		IRR_TEX_SMALL,
		IRR_TEX_MEDIUM,
		IRR_TEX_LARGE
	};
Then towards the bottom just after virtual core::stringc getVendorInfo() = 0;
add

Code: Select all

		//sets size of texture support desired
		void setTextureSizeSupport ( IRR_TEXTURESIZEOPT in ) { textureSizeSupport = in; }
		//gets current texture size support
		IRR_TEXTURESIZEOPT getTextureSizeSupport () { return textureSizeSupport; }		
		IRR_TEXTURESIZEOPT textureSizeSupport;
Then goto CNullDriver.cpp just after

Code: Select all

	#ifdef _DEBUG
	setDebugName("CNullDriver");
	#endif
add

Code: Select all

textureSizeSupport = IRR_TEX_LARGE; //default to full texture size support

then in
CNullDriver::loadTextureFromFile(io::IReadFile* file, const c8 *hashName ) change

Code: Select all

	if (image)
	{
		// create texture from surface
		texture = createDeviceDependentTexture(image, hashName ? hashName : file->getFileName() );
		os::Printer::log("Loaded texture", file->getFileName());
		image->drop();
	}
to

Code: Select all

	if (image)
	{
		if (textureSizeSupport == IRR_TEX_LARGE) {
			// create texture from surface
			texture = createDeviceDependentTexture(image, hashName ? hashName : file->getFileName() );
			os::Printer::log("Loaded texture", file->getFileName());
			image->drop();
		} else {
			// create texture from surface
			core::dimension2d<s32> texSize = image->getDimension();
			f32 sizeMode = 1.0f;
			switch (textureSizeSupport) {
				case IRR_TEX_TINY:
					sizeMode = 0.10f;
					break;
				case IRR_TEX_SMALL:
					sizeMode = 0.25;
					break;
				case IRR_TEX_MEDIUM:
					sizeMode = 0.50;
					break;
				case IRR_TEX_LARGE:
					sizeMode = 1.0f;
					break;
			}
			texSize.Width = (s32)ceil((f32)texSize.Width * sizeMode);
			texSize.Height = (s32)ceil((f32)texSize.Height * sizeMode);

			IImage * ImageTmp = new CImage(image->getColorFormat(), texSize);
			image->copyToScaling(ImageTmp);
			
			texture = createDeviceDependentTexture(ImageTmp, hashName ? hashName : file->getFileName() );
			os::Printer::log("Loaded texture", file->getFileName());
			image->drop();
			ImageTmp->drop();
		}
	}
Example usage:
driver->setTextureSizeSupport(video::IRR_TEX_MEDIUM);

Tiny Support is about 10th the size of the texture
Image

Medium is 1/2 the size
Image

You can change the Texture Size Support at any time before loading textures. You could easly setup options for characters to have their own texture size settings and enviroment, FX, etc.

It's been tested against the latest SVN and on OSX, Linux and Windows


Course this does the change at load time, you could how ever save it back to disc, so next time it wouldn't have to load up the entire texture.

Thx
V
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

yes, it's a prety nice idea !!! :)

but I see a problem with the tiny size...
remember texture dimensions have to be in power of 2 (2^n)...
1/2 and 1/4 are no problem, but with 1/10 for IRR_TEX_TINY you'll never get a suitable dimension !!! :shock:

for example with 1024:
IRR_TEX_LARGE = 1024 >>> OK
IRR_TEX_MEDIUM = 512 >>> OK
IRR_TEX_SMALL = 256 >>> OK
IRR_TEX_TINY = 102.4 >>> BAD

maybe 1/8 (0.125) would be better for tiny, then the result will be 128 ???
and I bet your 1st screenshot will look better than... ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
varmint
Posts: 46
Joined: Fri Oct 06, 2006 4:33 pm

Post by varmint »

Acki wrote:yes, it's a prety nice idea !!! :)

but I see a problem with the tiny size...
remember texture dimensions have to be in power of 2 (2^n)...
1/2 and 1/4 are no problem, but with 1/10 for IRR_TEX_TINY you'll never get a suitable dimension !!! :shock:

for example with 1024:
IRR_TEX_LARGE = 1024 >>> OK
IRR_TEX_MEDIUM = 512 >>> OK
IRR_TEX_SMALL = 256 >>> OK
IRR_TEX_TINY = 102.4 >>> BAD

maybe 1/8 (0.125) would be better for tiny, then the result will be 128 ???
and I bet your 1st screenshot will look better than... ;)
Actually I ended up using 0.0625 so the resulting would be 64 for tiny. And no the above screen shot will not look any better as the texture size of the dwarf starts at 512 and by the time it gets reduced to tiny support it's 32 or in the screenshot above 51.. either way your not going to get much detail at that res :D

Below are some links to what it looks like using 1024x1024 as a base
http://shadow.krabbit.com/varmint/sizes ... nysize.png
http://shadow.krabbit.com/varmint/sizes ... llsize.png
http://shadow.krabbit.com/varmint/sizes ... umsize.png
http://shadow.krabbit.com/varmint/sizes ... llsize.png
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

yeah, right, when the original texture already is small than you can't assume to get a better result... ;)
I just had your comment about using 1024x1024 textures in mind... :lol:

maybe you should also change the code in your post to the correct value for tiny, too ???
just for those who will just copy/paste the code... ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Yeah this is a good idea, very useful for performance scaling. If a computer is low end, no need to create different resolution textures, just use this. :D

Yet another useful idea Varmint.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The following will get a smaller image size based on a quality setting, will always get you a power of two sized result, and doesn't require floating point math.

Code: Select all

enum E_TEXTURE_QUALITY 
{ 
  ETS_HIGHEST = 0u, 
  ETS_HIGH    = 1u, 
  ETS_MEDIUM  = 2u, 
  ETS_LOW     = 3u, 
  ETS_LOWEST  = 4u, 
}; 

core::dimension2di get_dimension_for_quality (const core::dimension2di& d, E_TEXTURE_QUALITY q) 
{ 
  core::dimension2di r (1, 1); 

  // 
  // find the next larger power of 2 height and width 
  // 

  while (r.Width  < d.Width) 
    r.Width  <<= 1; 

  while (r.Height < d.Height) 
    r.Height <<= 1;  

  // 
  // if d is non-power-of-two, then reduce size to next 
  // smaller power of two value. i.e. 190x65 => 128x64 
  // 

  if (r.Width != d.Width) 
    r.Width >>= 1; 

  if (r.Height != d.Height) 
    r.Height >>= 1; 

  // 
  // now reduce the size based on quality setting 
  // 

  for (u32 i = 0; i < q; ++i) 
  { 
    if (r.Height != 1) 
      r.Height >>= 1; 

    if (r.Width  != 1) 
      r.Width  >>= 1; 
  } 

  return r; 
}
Travis
Last edited by vitek on Sun Mar 23, 2008 12:22 am, edited 1 time in total.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Someone wrote:Yet another useful code vitek.
8)

And thank you both, that's a great idea with now even better implementation!

Thanks guys, I could really use it.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

It's really nice:) Good work Varmint!
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

I have to agree with BlindSide. This is great, varmint, for performance scaling, and such a simple idea. I guess KISS applies to this. :D
TheQuestion = 2B || !2B
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Re: Dynamic Texture Size Support

Post by rogerborg »

Thanks for sharing; that looks really useful.
varmint wrote:Course this does the change at load time, you could how ever save it back to disc, so next time it wouldn't have to load up the entire texture.
IIRC, GTA 3 did that, but it seems more usual to just scale them on each run, based on a user preference and/or VRAM size.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

Why not just drop the top mips of any texture above a threshold based on the host hardware - say 1024x1024 or 512x512? This could significantly reduce texture memory usage without losing detail in smaller textures via this "scale every texture" method.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

sio2 wrote:Why not just drop the top mips of any texture above a threshold based on the host hardware - say 1024x1024 or 512x512? This could significantly reduce texture memory usage without losing detail in smaller textures via this "scale every texture" method.
Good point, I think user-adjustable mipmapping is on the agenda for Irrlicht developement.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

I'm not sure if using mipmap-lod bias actually drop the higher mips from vidmem - possibly driver dependant. Probably better to not load those mip levels in the first place.

Since it's usually a significant performance boost to have all level geometry use mipped textures the best solution is probably to just not upload "large" mip levels at texture load-time. This will save texture memory and not make small textures look blurred.
Post Reply