Non Power of Two texture work around?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Cloudef
Posts: 123
Joined: Wed Dec 03, 2008 9:02 pm
Location: Finland

Non Power of Two texture work around?

Post by Cloudef »

Hi,
I'm new to irrlicht and I'm doing 2d game. Ive got so far all basic loading and stuff working, but i hate that I'm not apple to load non power of two textures and 90% of my media is non power of 2.

I tough if there would be some workarounds? Lets say like re-size image canvas on fly or combine the image with invisible power of 2 image?
Lambda
Posts: 126
Joined: Wed Feb 27, 2008 3:00 pm
Location: Spain, Huelva
Contact:

Post by Lambda »

just dont use power of 2 images, you can resize these images, i am using npo2 textures for the gui of my game and everything is working fine :)
Image
Cloudef
Posts: 123
Joined: Wed Dec 03, 2008 9:02 pm
Location: Finland

Post by Cloudef »

The thing is, that i moved from another engine and i have lot of images that are not power of two. Also i don't want to re-size the image only the canvas. If there is tool that can handle multiple image canvas then i could re-size them.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Can you show your code to drw the image and screenshots to explain which errors you encounter?
Cloudef
Posts: 123
Joined: Wed Dec 03, 2008 9:02 pm
Location: Finland

Post by Cloudef »

Sure

I load it normally using:

Code: Select all

Player[id]->state[state].body[parti].s[state2].i = Driver->getTexture(str2.c_str());
and draw using:

Code: Select all

void drawPlayer(int id) {
 int state=Player[id]->State;
 int state2=Player[id]->State2;
 int i;
 dimension2d<s32> imgSize;
 for(i=0;i < 3;i++) {
  if(Player[id]->state[state].body[i].s[state2].exist) {
   imgSize = Player[id]->state[state].body[i].s[state2].i->getOriginalSize();
   Driver->draw2DImage(Player[id]->state[state].body[i].s[state2].i, core::position2d<s32>(Player[id]->state[state].body[i].s[state2].x,Player[id]->state[state].body[i].s[state2].y),core::rect<s32>(0,0,imgSize.Width,imgSize.Height), 0,video::SColor(255,255,255,255), true);
  }
 }
}
It draws it okay. But because image is not power of two it gets really "messy".
[/code]
Lambda
Posts: 126
Joined: Wed Feb 27, 2008 3:00 pm
Location: Spain, Huelva
Contact:

Post by Lambda »

Cloudef wrote:Sure

I load it normally using:

Code: Select all

Player[id]->state[state].body[parti].s[state2].i = Driver->getTexture(str2.c_str());
and draw using:

Code: Select all

void drawPlayer(int id) {
 int state=Player[id]->State;
 int state2=Player[id]->State2;
 int i;
 dimension2d<s32> imgSize;
 for(i=0;i < 3;i++) {
  if(Player[id]->state[state].body[i].s[state2].exist) {
   imgSize = Player[id]->state[state].body[i].s[state2].i->getOriginalSize();
   Driver->draw2DImage(Player[id]->state[state].body[i].s[state2].i, core::position2d<s32>(Player[id]->state[state].body[i].s[state2].x,Player[id]->state[state].body[i].s[state2].y),core::rect<s32>(0,0,imgSize.Width,imgSize.Height), 0,video::SColor(255,255,255,255), true);
  }
 }
}
It draws it okay. But because image is not power of two it gets really "messy".
[/code]
if you want your image smoothed you need to change a line in the driver .cpp, its easy.

in CD3D9Driver.cpp search for

Code: Select all

pID3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
and replace with

Code: Select all

pID3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Image
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

@Cloudef: A screenshot would be nice...

@Lambda: Beware of the "everything is working" - in this case it might depend very much on the card. I had my GUI working here perfectly, but then someone tested it with a card not supporting npot and it got all messed up. A surprising number of modern cards still don't do that.

Anyway, while I'm not exactly sure which problem Cloudef is facing, in my case (for the GUI) I found no other way but to change the engine. What I did was adding some padding to the textures. Now unfortunately parts of the stuff I had to change for that have been rewritten since then in the engine, so I have no working patch for that right now :-( The old patches I used for that are still available here (search for npot). But in the current state you can only use them as some startingpoint for an own implementation.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
cecil0812
Posts: 12
Joined: Tue Jul 29, 2008 4:57 pm

Post by cecil0812 »

I just finished up writing a little 2D sprite based RPG in Irrlicht. I had to deal with this very issue.

First, converting your images to power of two isn't as bad as you might think. Download The Gimp or Paint.NET or something and just add padding to your images.

Then, add a blit color to your images. I used a bright green color. You can tell Irrlicht to make this color transparent when it loads it and voila. Power of two textures that are actually the size you want.

Alternatively, when you get the texture for drawing it, you can specify the rectangle in the image to draw, thus making your image power of two, but only displaying the rectangle (which may or may not be power of two).

Here's a little code I used:

Code: Select all

video::ITexture* myImage = driver->getTexture("someImage.png");
driver->makeColorKeyTexture(myImage, core::position2d<s32>(0, 0));
I always had the Color Key be at the first pixel of the image which made it easy to find at all times.

Let me know if you need more info :)
jontan6
Posts: 278
Joined: Fri Jun 13, 2008 5:29 pm

Post by jontan6 »

isnt it that irrlicht convert npot textures to pot on load? just a guess
cecil0812
Posts: 12
Joined: Tue Jul 29, 2008 4:57 pm

Post by cecil0812 »

jontan6 wrote:isnt it that irrlicht convert npot textures to pot on load? just a guess
No, it doesn't. It just warns you about a slow unlock with non power of 2 (if using software mode). With my video card and OpenGL with non power of 2, it crashed hard. With DirectX, it didn't crash but it didn't clip correctly.

Power of 2 is the way to go :)
Cloudef
Posts: 123
Joined: Wed Dec 03, 2008 9:02 pm
Location: Finland

Post by Cloudef »

I guess i have to then find batch converter and convert a lot of images.

Screen of problem:

Image
Original

Image
Irrlicht


Oh and the media is not mine btw, I'm currently reverse engineering Maple Story and creating similar engine that it is. The old rendering engine that i used had some limitations to my needs so i moved to irrlicht.
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

jontan6 wrote:isnt it that irrlicht convert npot textures to pot on load? just a guess
I think it scales per default to pot if the card does not support npot textures. At least I think it does so in OpenGL and DX. That's just not always what you might want sometimes you want scale, sometimes you prefer padding.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, Irrlicht scales to POT for the HW accelerated drivers, because those can fail otherwise. The SW driver does handle NPOT, not sure about burningsvideo. We already had some suggestions on how to integrate padding into this scenario, but we'd like to have a clean way without too many caveats for this problem. Right now it's not possible to specify the proper source rectangle as part of the image, i.e. one is forced to use alpha channel for the padded images. While this is often no problem, it needs to be properly adapted to all parts of the engine. Patches are welcome, please put them on the patch tracker :D
cecil0812
Posts: 12
Joined: Tue Jul 29, 2008 4:57 pm

Post by cecil0812 »

Hmmm, if it scales to POT on OpenGL and DirectX...

Like I said before, for DirectX, it made my sprites look funky. The auto scaling was probably a little off.

For OpenGL, whatever it was doing just crashed the program.

This was all using Irrlicht 1.4.

Once I converted everything to POT, everything looked and ran great.
SwitchCase
Posts: 170
Joined: Sun Jul 01, 2007 11:41 pm
Location: Manchester, UK

Post by SwitchCase »

For hardware which can't do npot sizes OR you don't have the required opengl extensions available (btw i dont know about d3d) then you can scale your image with something like...

Code: Select all

int width = imageWidth;
int height = imageHeight;

int i;
bool sizeToFit = false;

// Scale image width to next pot size		
if( (width != 1) && (width & (width - 1)) )
{
	i = 1;
	while( (sizeToFit ? 2 * i : i) < width )
		i *= 2;
	width = i;
}
		
// Scale image height to next pot size		
if( (height != 1) && (height & (height - 1)) )
{
	i = 1;
	while( (sizeToFit ? 2 * i : i) < height )
		i *= 2;
	height = i;
}
		
// Scale image down if now larger than the maximum texture size
while( (width > kMaxWidth) || (height > kMaxHeight) )
{
	width /= 2;
	height /= 2;
	imageWidth *= 0.5;
	imageHeight *= 0.5;
}
... then proceed to creating the texture with these dimensions but drawing them using the original image dimensions.

:P
Post Reply