Smoother stretching of 2D images in OpenGL

A forum to store posts deemed exceptionally wise and useful
Post Reply
specialtactics
Posts: 17
Joined: Tue Dec 09, 2003 9:03 am
Location: Germany

Smoother stretching of 2D images in OpenGL

Post by specialtactics »

Hi,

today i started looking closer at the GUI of my game. IGUIImage is nice, but simply lacks scaling the image - I don't want a different image file for every resolution. Since there already is a overloaded version of draw2DImage in the VideoDriver, that can scale the image, changing GUIImage is simple: in CGUIImage.cpp replace

Code: Select all

if (Texture) {
		driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner, 
			core::rect<s32>(core::position2d<s32>(0,0), Texture->getOriginalSize()),
			&AbsoluteClippingRect, video::SColor(255,255,255,255), UseAlphaChannel);
with

Code: Select all

if (Texture) {
		driver->draw2DImage(Texture, AbsoluteRect, 
			core::rect<s32>(core::position2d<s32>(0,0), Texture->getOriginalSize()),
			&AbsoluteClippingRect, 0, UseAlphaChannel);
Now this really does scale the image, but it looks like crap both in OpenGL and Direct3D. To make it look better in OpenGL (i never used Direct3D before and OpenGL seems to work better for me anyhow, so I just looked in the OpenGLDriver code) changing the magnification filter from nearest to linear helps a lot. In COpenGLDriver.cpp around line 1530 replace

Code: Select all

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
with

Code: Select all

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
These are both quick hacks that seem to work, at least during the 15minutes that I have been testing them. :)
specialtactics
Posts: 17
Joined: Tue Dec 09, 2003 9:03 am
Location: Germany

Post by specialtactics »

ok, a small update. I wanted to fill the entire window with a bitmap using CGUIImage as described above, but there was a one pixel wide border on the left and bottom, when creating the image like this:

Code: Select all

g_gui->addImage(rect<s32>(0, 0, resolutionX-1, resolutionY-1));
after some playing around with minus one here, plus one there i came up with the smallest values to fill the entire screen are:

Code: Select all

g_gui->addImage(rect<s32>(-1, 1, resolutionX-1, resolutionY+1));
:shock:
I have no idea, why. But it seems to work and that's enough for me right now. Seems to work for both OpenGL and Direct3D.
Guest

Post by Guest »

yeah, intersting posts. SOmething I have been upset with irrlicht for some time is its 2D handling (stretching/scaling/pixelleting) of quads. I DO know D3D as I started my own engine in it but gave up when I saw how cool irrlicht was ;) and in that the -1 thing is a give because you want to map texel perfect. (similar issues to the 0.5f thing). However I could take a texture in my engine (512x512 say) and map it perfectly to ANY screen size (800x600 for example) and it would sample up nicely and still be a square pow 2 texture which is ideal. How to do this kind of thing in irrlicht escapes me at this moment, though I admit I have got as much into the 2D stuff yet when editing the source code. I will try out your suggestions but will also make sure mip maps are OFF before loading the textures (no good for guis) and that all textures are original pow2.

I am sure the built in scaling of gui stuff uses integers rather than floats and that is why we have these issues.. am I correct??
Post Reply