PDA

View Full Version : Resolution Independent Drawing



glorified_ameba
03-27-2007, 07:21 PM
Hello all,

I have just discovered ClanLib a week ago and have been playing with it non-stop. It is an amazing library so far.

But I have one question about the library: Is it possible to do resolution independent drawing of sprites? For example, I would like to draw a sprite that occupies a small portion of the screen, and no matter what resolution the application uses I would like that sprite to occupy the same amount of the visible screen.

Thank you for any help you can provide.


Rados Jovanovic

Chambers
03-28-2007, 02:25 AM
Absolutely. If you're using native OpenGL to draw, then use this instead of gluPerspective:

gluOrtho2D(0,100,0,100);

This sets up the render window to be treated as if it were 100 units across and 100 units down, no matter what the real resolution is (note that OpenGL will still draw in the real resolution of the window; it's just for convenience in specifying coordinates that it acts this way).

Now, when you pass coordinates (via glVertex) use 2D coordinates that represent the percentage of the screen you want.

For instance,

glBegin(GL_QUADS);
glVertex2i(0,0);
glVertex2i(0,10);
glVertex2i(10,10);
glVertex2i(10,0);
glEnd();

will draw a square that is 10% of the width of the screen, and 10% of the height.

The problem with this approach, naturally, is that it assumes that all screens are the same aspect ratio. Unfortunately, that's not the case; some are 4:3, some are 16:9, or 2:1, or 5:4, or 16:10, or any others that I've forgotten. When drawing this way on a screen you didn't anticipate, the image will be distorted.

So, we have to do a little extra math.

// Begin Code
float aspect = float(window.get_width()) / float(window.get_height());

int width(100*aspect);
int center(width/2);

gluOrtho2D(0,width,0,100);
// End Code

Now your window will be 100 units high, and 'width' units across. The advantage of this is that it will result in square pixels, so if you want a square that's half the height of the screen it would be 50 units across and down (50 units = 50% of the height).

The integer 'center' is defined for convenience (we also leave 'width' lying around, in case you need to reference it easily later).

glorified_ameba
03-28-2007, 03:10 PM
Hello Chambers and thank you for the quick reply.

It seems that I wasn't as clear in my question. I am a bit familiar how to do it in native OpenGL, but I was wondering if I can do such a thing with the ClanLib draw functions. For example, I would like this function:

surface->put_screen(50, 50);

to begin drawing the surface at the center of the screen. I have tried putting:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,100,0,100);
glMatrixMode(GL_MODELVIEW);

before the put_screen call, but nothing changed. I understand the aspect ratio problem, but I will worry about it later.

Oh, and I just realized that I am using the 0.6.5 version of ClanLib. Damn Ubuntu. I will install the newest one now. Maybe that will change things a bit.

Thank you again for the reply.


Rados

EDIT:
I have just installed ClanLib 0.8 and tried to do this again. The gluOrtho2D(0,100,0,100) function just zooms in the display, which is to be expected when I think about it. I'm still looking for a way to trick the draw command to be resolution independent.

glorified_ameba
03-28-2007, 05:30 PM
And, I think I found a solution:
If, for example, I want my native resolution to be 800x600 but I also want to let the user choose the resolution they want to play in, I can just create the window in that users resolution of choice (let's say 1024x768) and then add the following before my draw calls:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 800, 600, 0);
glMatrixMode(GL_MODELVIEW);

This way I can make sure that the game looks 100% the same at different resolutions. I do all my programming and testing for the 800x600 resolution and it will automatically scale to other resolutions. Of course, if the resolution is of some different aspect ratio everything will look stretched, but that's a different story.

Chambers
03-28-2007, 05:33 PM
Sure, you can do it like this:

surface->draw( CL_Rect(left, top, right, bottom), &my_gc);

Normally, the coordinates you pass would be pixel coordinates for the window. However, as you noticed, gluOrtho2D resizes the screen, so you can use whatever coordinates you like.