Ortho Etiquette

Started by
8 comments, last by glDino 22 years, 10 months ago
I am using gluOrtho2D() to create a 2D overlay for my menus, cursors, and Heads-Up displays. It looks great at the resolution I run it at... but the lower the res I try, obviously, the more screen space my 2D objects will take up because there are fewer pixels available. If I run at a super-low 640x480, a good deal of my overlay is off-screen (that''s not good!) So my question is, do I have to scale my textures and fonts to fit into the screen when the user changes resolution? If so, is there a proper or *recommended* way to do this? Basically, I just want my menu buttons and HUD items to be about the same size and have about the same spacing no matter what the res. I''m guessing this involves some kind of proportion or ratio calculations to figure out how many pixels to add as spacing at each res... but I''m really clueless. Thanks.
Advertisement
Hi there,

theoretically you could just call glScale(x,y,z);
to scale the geometry where

x := ScreenWidth / 640;
y := ScreenHeight / 480;
z := 1;

should work but havent tested it.
just try to move it ''into'' the screen (z--)
moving it ''away will shrink its size without damaging rendering speed...

good luck.
Oi Dino, you can''t Zoom in an Ortho screen. No mater the Z value is the size will remain the same. If i''m not mistaken the function to create an Ortho screen let''s you create your own resolution whatever your screen resolution is. So if you create a 640x480 Ortho screen it will be only the units. So the coordinate 320,240 will always be the center of the Ortho Screen (and the screen as well), evan if the window is actually 1024x768.

I think you sould look at NeHe''s Ortho Tutorial
Help me with my Isometric OpenGL engine.
Oi Dino, you can''t Zoom in an Ortho screen. No mater the Z value is the size will remain the same. If i''m not mistaken the function to create an Ortho screen let''s you create your own resolution whatever your screen resolution is. So if you create a 640x480 Ortho screen it will be only the units. So the coordinate 320,240 will always be the center of the Ortho Screen (and the screen as well), evan if the window is actually 1024x768.

I think you sould look at NeHe''s Ortho Tutorial
Help me with my Isometric OpenGL engine.
AK37, I understand that I can create the Ortho screen using my own coordinates, no matter what the window resolution. I am using 640x480 for Ortho. I have no problem keeping everything centered on the screen, its just that when the resolution (window size) changes, the Ortho stuff doesn''t (because it always uses the same coordinates!)

When I run the program at the SAME resolution as the coordinate system I use for the Ortho screen, everything is normal both position and size-wise. If I run the demo at a smaller resolution, the Ortho stuff gets bigger and takes up the whole screen (even runs off of the screen!). When I run the demo at a higher resolution, the geometry does not change size (because there is enough surface area in the view frustum), so the user has to squint to see it! It should look the same at any resolution.

Try this to see what I mean... fire up Quake III Arena if you have it.
Notice the size of the buttons on the main menu.
Now change the res to 320x240. Notice the size of the same buttons on the main menu -> No Difference!
Now change the res to 1280x1024. The buttons are still the same size!

I''m not making the assumption that QuakeIII uses Ortho projections for the menu, but that is the effect I want to achieve in my menu/HUD.

I understand the concept of MButchers'' method, but those divisions will produce a decimals... can these be used with Ortho mode? I tried something like this at the beginning of my rendering code:

static float aspect[2] =
{ g_window->init.height / 640,
g_window->init.width / 480
};

glScalef(aspect[0], aspect[1], 1);
glBegin(GL_QUADS);
...
glEnd();

But it didn''t do the trick.
I think I''m just doing it wrong.
I just hope my menu class doesn''t need a total re-write!

Does anyone have a working demo w/ source of how to do this?
Either that, or any further advice/internet resources would be very greatly appreciated.

Thanks to all who replied already.
I''m not sure about the proper way to do this but I can tell you how I am doing my 2d overlays that will look right at any dimension. Instead of using Ortho I use regular projection mode. I load my identity, translate by (0, 0, -12). Then (-8, -6, -2.5) to (8, 6, -2.5) are my screen coordinates from bottom left to top right. It may not be 100% exact but it is close enough that I can''t tell anyways


This should look the same on all standard resolutions that use a 4/3 width/height ratio.

640/480 800/600 1024/768 etc...

With this setup it is best to think of your screen as 800x600 and use a function to draw your primitive.

Say for instance you wanted to draw a rectangle on the screen with the current texture. You could use th is function:

void drawRect( int x1, int y1, int x2, int y2 )
{
float xx1, xx2;
float yy1, yy2;

// Convert screen coordinates to world coordinates
// Multiply each coordinate by 2, subtract 800 from x axis,
// 600 from y axis. Invert the y coordinates since opengl
// textures consider 0, 0 to be bottom left and screen coords
// are normally 0,0 at top left.
// Now divide all by 100.

xx1 = ((float)((float)x1*2)-800.0f);
xx1 /= 100.0f;

xx2 = ((float)((float)x2*2)-800.0f);
xx2 /= 100.0f;

yy1 = -((float)((float)y1*2)-600.0f);
yy1 /= 100.0f;

yy2 = -((float)((float)y2*2)-600.0f);
yy2 /= 100.0f;

//draw our rectangle

glBegin( GL_QUADS );
glTexCoord2f( 0.0f, 0.0f ); glVertex3f( xx1, yy2, -2.5f );
glTexCoord2f( 1.0f, 0.0f ); glVertex3f( xx2, yy2, -2.5f );
glTexCoord2f( 1.0f, 1.0f ); glVertex3f( xx2, yy1, -2.5f );
glTexCoord2f( 0.0f, 1.0f ); glVertex3f( xx1, yy1, -2.5f );
glEnd();
}

You will need to load identity and translate back -12 on Z and set your texture, disable depth test etc before using this function. For instance here is how I draw my splash screen:


void Game3D::drawSplash()
{
//Save our current matric
glPushMatrix();
//Move to our base position and orientation
glLoadIdentity();
//Set full original texture colors
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
//Select our splash screen texture
glBindTexture(GL_TEXTURE_2D, level->getSysTexture(SPLASH) );

//Disable depth testing so that any objects that are closer to
//the viewer will be overwritten anyways.
glDisable( GL_DEPTH_TEST );

//Disable blending so it is not transparent
glDisable( GL_BLEND );

//Move -12 on Z
glTranslatef( 0.0, 0.0, -12.0f );

//Pretend we are in 800 x 600 and fill screen with texture
drawRect( 0, 0, 800, 600 );

//Flush it
glFlush();

//Restore our matrix and re-enable depth testing
glPopMatrix();
glEnable( GL_DEPTH_TEST );
}

Obviously if you had alot of items to draw you would not load identity and all that each time just draw them all between the glTranslatef and glFlush lines.



Don''t know if this will be useful to you but it works great for me

Seeya
Krippy
Oh yeah almost forgot. That is assuming your perspective is set like mine

gluPerspective(45.0f,(GLfloat)gamewidth/(GLfloat)gameheight,(GLfloat)nearclip, (GLfloat)farclip );


If I have something different going on like zooming in (I multiply my perspective by a zoom factor for weapon zooming) just make sure I save my old perspective, set my current perspective to 45.0, draw my stuff and then set my perspective back the way it was.



Probably not the best way but it works every time.

Seeya
Krippy

Krippy,

Thank you. I'll definately take this method into consideration.

A couple of questions...

1) what if I use a 90 degree prespective instead of 45?
2) what is the best angle to use for a walkaround FPS type game?

-Dino


Edited by - glDino on June 8, 2001 10:03:12 PM
I''m not sure why it is so, but after playing around a few minutes I found that in drawRect if you change it to divide everything by 41.5 instead of 100 it will look right at 90 degree perspective.

Not sure there is a best perspective to use. Whatever looks like it works the best for you is probably the best

I use 45 but 90 is cool too

This topic is closed to new replies.

Advertisement