emulating unavailable resolutions

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
ngc92
Posts: 11
Joined: Thu Nov 19, 2009 3:56 pm

emulating unavailable resolutions

Post by ngc92 »

i am developing a simple 2D game as free time project and decided to use a very low resolution (400 x 300) to be able to use low res grafics.

but unfortunately, some recent screens don't provide a 400 x 300 fullscreen resolution anymore, but i want to stay with this resolution.

My first approach was to choose a higher resolution and to draw anly to the center of the screen leaving a black border arround the game (so, this approach used adding a constant to all coordinates and use a cliprect for the area to draw to).

Then I noticed the sourceRect parameter of beginScene, and to test how it works, i passed my clip rect as sourceRect, and it seems to work fine.

then i decided to stop shifting the whole drawing, because i thought with sourceRect i can draw only in the top left corner and stretch it to fit.

unfortuneately, now everything seems to be shifted up and a black border remains on the bottom.

Thus, my questions are:
What does sourceRect exactly do?
What is the best way to strecht the whole rendering?
(i think, another possibility would be using a RTT)

thanks for answering

edit:
if i add half the frame with to the source rect, the black border disapperas, so everything that passes the clipRect (= sourceRect) is also drawn to the screen.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

You don't need an RTT, just draw to the screen using a full screen quad, you can find a simple one here:

http://irrlicht.sourceforge.net/phpBB2/ ... 077#183077

I think by default it just draws to the entire screen, so you don't need to adjust the scale. :D
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

or maybe driver->setViewPort(...) can help you ??? ;)
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 »

Acki, are you sure? I think it will just restrict drawing to a small section of the screen, which he's already tried.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
ngc92
Posts: 11
Joined: Thu Nov 19, 2009 3:56 pm

Post by ngc92 »

At first, thanks for the suggestion of quad drawing, at least i am able to scale everything correct....

it helps me at least if i use OpenGL driver...
but i don't see why i don't need RTT. Now, I use a 400x300 Texture and render everything into it, and then i draw to the screen using the method you proposed.

but this leads to strange results in software drivers.

can someone tell me what the following functions really do?
driver->setViewPort(...)
beginScene with sourceRect Parameter

i figured out how to make sourceRect work with SW driver, but i don't understand why it works. My drawing operations are performed in the area from 0,0 to 400,300. If I set sourceRect to be

Code: Select all

rect<s32>(vector2di(0, 300), dimension2du(400,300))
(so this is the rect from (0,300) to (400, 600)), everything is presented correcly.

The next problem i noticed is, that the sourceRect parameter is passed to beginScene but it is saved as a pointer and seems to be not needed until end scene is called, so if map_area is the zone i draw to (i.e. the clipRect), the following code worked fine (but it seems buggy to me that it works):

Code: Select all

 driver->beginScene(false, false, video::SColor(0,0,0,0), video::SExposedVideoData() , &map_area);
 // ...
 // 2D drawing using map_area as clipRect
 // ...
 map_area.UpperLeftCorner.Y += SCREEN_HEIGHT;
 map_area.LowerRightCorner.Y += SCREEN_HEIGHT;
 driver->endScene();
 map_area.UpperLeftCorner.Y -= SCREEN_HEIGHT;
 map_area.LowerRightCorner.Y -= SCREEN_HEIGHT;
maybe someone can clarify whether i don't understand the intended behaviour of sourceRect or whether this is a bug in the current implementation.

Furthermore, any suggestions on a solution for full screen drawing with a different resoultion that works with OpneGL and Software Driver as well is appreciated.

Thanks[/code]
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

From the docs:

sourceRect: Pointer to a rectangle defining the source rectangle of the area to be presented. Set to null to present everything. Note: not implemented in all devices.

I'd render to an RTT and then display it on a quad, much like you do post-processing. Note though, that the software driver doesn't do 3D rendering properly at all, but the Burning's renderer somewhat does. If you use a quad with a RTT, it might not display properly. Which are you using? This may be the source of your problems.
ngc92
Posts: 11
Joined: Thu Nov 19, 2009 3:56 pm

Post by ngc92 »

i've read the docs, but i don't understand why the rectangle i use for clipping (0,0;400,300) is different from the one i use for beginScene() (0,300;400;600). Also, the behaviour of storing only the pointer is not what i expect by reading the docs.

rendering to a RTT works quite fine for OpenGL but is unusable for Software Driver and Burningsvideo.

here you can see the relevant parts of the programme. it works, but i wonder why because the sourceRect is outside the area i draw to. Maybe as a hint, i noticed that a rect of (0,0; 400;300) causes the lower half of my scene to be drawn on the upper half of the screen

startup

Code: Select all

driver = device->getVideoDriver();
		
	core::vector2di dif = core::vector2di((driver->getCurrentRenderTargetSize().Width - SCREEN_WIDTH),
								(driver->getCurrentRenderTargetSize().Height - SCREEN_HEIGHT));

if (driver->getDriverType() == EDT_OPENGL && dif.X != 0 && dif.Y != 0){
	RTT = driver->addRenderTargetTexture(core::dimension2d<u32>(SCREEN_WIDTH, SCREEN_HEIGHT), "unscaled");
		
	driver->setTransform(irr::video::ETS_WORLD, core::matrix4());
	driver->setTransform(irr::video::ETS_VIEW, core::matrix4());
	driver->setTransform(irr::video::ETS_PROJECTION, core::matrix4());
}else{
	RTT = 0;
}
begin scene:

Code: Select all

if(RTT){		
	driver->beginScene(false, false, video::SColor(0,0,0,0));
	driver->setRenderTarget(RTT, false, false, 0);
}else{
	driver->beginScene(false, false, video::SColor(0,0,0,0), video::SExposedVideoData() , &map_area);	// 2D Grafik - zbuffer egal
}
end scene

Code: Select all

if(RTT){
	video::S3DVertex Vertices[6];
	const irr::u16 indices[6] = {0, 1, 2, 3, 4, 5}; 
	
	Vertices[0] = irr::video::S3DVertex(-1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         irr::video::SColor(0xffffffff), 0.0f, 1.0f);
      	Vertices[1] = irr::video::S3DVertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         irr::video::SColor(0xffffffff), 0.0f, 0.0f);
      	Vertices[2] = irr::video::S3DVertex( 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         irr::video::SColor(0xffffffff), 1.0f, 0.0f);
      	Vertices[3] = irr::video::S3DVertex( 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         irr::video::SColor(0xffffffff), 1.0f, 1.0f);
      	Vertices[4] = irr::video::S3DVertex(-1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         irr::video::SColor(0xffffffff), 0.0f, 1.0f);
      	Vertices[5] = irr::video::S3DVertex( 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         irr::video::SColor(0xffffffff), 1.0f, 0.0f); 
        
	driver->setRenderTarget(0, false, false, 0);
	video::SMaterial old = driver->getMaterial2D();
	video::SMaterial nem = old;
	nem.setTexture(0, RTT);
	driver->setMaterial(nem);
	   	
	driver->drawIndexedTriangleList(&Vertices[0], 6, &indices[0], 2); 
		
	driver->setMaterial(old);
}

// WHY MUST MAP_AREA BE CHANGED HERE??
map_area.UpperLeftCorner.Y += SCREEN_HEIGHT;
map_area.LowerRightCorner.Y += SCREEN_HEIGHT;
driver->endScene();
map_area.UpperLeftCorner.Y -= SCREEN_HEIGHT;
map_area.LowerRightCorner.Y -= SCREEN_HEIGHT;
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I am doing something very similar.

I have designed a "GUI" (not using Irrlicht system, but a simpler "GUI") which has a fixed resolution of 1024x768. And i draw bits using the draw2DImage method and a custom routine to draw batches of 2D bits of textures into rectangles.

The advantage of this way is that you may have any "destination" resolution, while the source resolution is fixed.

This is my routine to draw scaled 2D rectangles.
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=38525

The good thing is that the drawings are scaled, the textures can be filtered and everything is accelerated using batches of images, so this maybe useful for you.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Valmond
Posts: 308
Joined: Thu Apr 12, 2007 3:26 pm

Post by Valmond »

I'd go for a 800x600 resolution using a texture 800x600, updating it manually every frame (that wouldn't
take too much time on an ordinary CPU and you wouldn't have any filtering problems) and then draw it on screen.

Just an idea though.
Post Reply