PDA

View Full Version : glOrtho not working?



philzz
08-27-2013, 12:12 PM
My application (GLUT w/ XCode 4) loads a 640x480 flat image to the window (also 640x480). When I attempt to resize it, the window resizes with the new width and height values, but the image's size stays at 640x480 on the top-left corner. In addition, if I load the application with fullscreen, it shows the 640x480 image on the top-left, and I see a black background to the right and bottom. So, even on first resize, it's not working as expected.

I don't know if this has to do with using the GL_TEXTURE_RECTANGLE_EXT extension, or if it's my glEnable2D() function because each is setting glOrtho again. Any thoughts on how to stretch the image correctly with the new resize?

Here's my glOrtho code:



void resizeScene(GLint w, GLint h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (h == 0)
h = 1;

glViewport(0, 0, w, h);

if( w <= h )
{
glOrtho(-1, 1, -1 * (GLfloat) h / (GLfloat) w, (GLfloat) h / (GLfloat) w, -1, 1);
}
else
{
glOrtho(-1 * (GLfloat) w / (GLfloat) h, (GLfloat) w / (GLfloat) h, -1, 1, -1, 1);
}

glMatrixMode(GL_MODELVIEW);
}


And when I'm rendering, I use the following using the GL_TEXTURE_RECTANGLE_EXT extension.



glBindTexture(GL_TEXTURE_RECTANGLE_EXT, g_uTextureID);
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,GL_RGB, g_iTextureWidth, g_iTextureHeight, 0,GL_RGB, GL_UNSIGNED_BYTE, data);

// Render a quad
// Instead of the using (s,t) coordinates, with the GL_NV_texture_rectangle
// extension, you need to use the actual dimensions of the texture.
// This makes using 2D sprites for games and emulators much easier now
// that you won't have to convert :)

glBegin( GL_QUADS );


glTexCoord2i( 0, g_iTextureHeight );
glVertex2i( 0, 0 );

glTexCoord2i( g_iTextureWidth, g_iTextureHeight );
glVertex2i( g_iTextureWidth, 0 );

glTexCoord2i( g_iTextureWidth, 0 );
glVertex2i( g_iTextureWidth, g_iTextureHeight );

glTexCoord2i( 0, 0 );
glVertex2i( 0, g_iTextureHeight );

glEnd();


During every render cycle, it calls glEnable2D/glDisable2D.



void glEnable2D(void)
{
GLint iViewport[4];

// Get copy of viewport.
glGetIntegerv(GL_VIEWPORT, iViewport);

// Save a copy of the projection matrix so it can be returned.
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

// Set up orthographic projection.
glOrtho(iViewport[0], iViewport[0] + iViewport[2],
iViewport[1]+iViewport[3], iViewport[1], -1, 1);

glMatrixMode(GL_MODELVIEW);

glPushMatrix();
glLoadIdentity();

// Disable lighting and depth testing while in 2D.
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT);

glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
}

Eric...
08-27-2013, 07:51 PM
Hi,

I don't see it in your code above, but do you call glEnable2D() function before rendering the quad ? I suppose it's the case if your quad stays in the corner when you resize the window.
You are calling glOrtho() both in resizeScene() and glEnable2D() : the one from resizeScene() is superseded by the one from glEnable2D() so you can remove glOrtho() from resizeScene().

About the quad, if you want to keep it in the middle of the window:

GLint iViewport[4];
glGetIntegerv(GL_VIEWPORT, iViewport);
int x = (iViewport[3] - g_iTextureWidth) / 2;
int y = (iViewport[4] - g_iTextureHeight) / 2;

glBegin( GL_QUADS );
glTexCoord2i( 0, g_iTextureHeight );
glVertex2i( x, y );

glTexCoord2i( g_iTextureWidth, g_iTextureHeight );
glVertex2i( x + g_iTextureWidth, y );

glTexCoord2i( g_iTextureWidth, 0 );
glVertex2i( x + g_iTextureWidth, y + g_iTextureHeight );

glTexCoord2i( 0, 0 );
glVertex2i( x, y + g_iTextureHeight );
glEnd();

If you want to resize it with the window and keep the aspect ratio (with glOrtho(iViewport[0], iViewport[0] + iViewport[2], iViewport[1]+iViewport[3], iViewport[1], -1, 1); in glEnable2D()):

// get viewport dimensions
GLint iViewport[4];
glGetIntegerv(GL_VIEWPORT, iViewport);

// get maximal render size keeping image aspect ratio
float w = (float)g_iTextureWidth;
float h = (float)g_iTextureHeight;
float ratio_w = (float)iViewport[3] / w;
float ratio_h = (float)iViewport[4] / h;
float ratio = ratio_w >= ratio_h ? ratio_h : ratio_w;
w *= ratio;
h *= ratio;

// keep image centered
float x = (iViewport[3] - w) * 0.5f;
float y = (iViewport[4] - h) * 0.5f;

// draw quad
glBegin( GL_QUADS );
glTexCoord2i( 0, g_iTextureHeight );
glVertex2f( x, y );

glTexCoord2i( g_iTextureWidth, g_iTextureHeight );
glVertex2f( x + w, y );

glTexCoord2i( g_iTextureWidth, 0 );
glVertex2f( x + w, y + h);

glTexCoord2i( 0, 0 );
glVertex2f( x, y + h);
glEnd();

This is just one way to do it, and i just wrote the code for the reply, so it is not tested !

Another point, not related, you must be aware that you are transfering your image to the gpu each time you render the quad (glTexImage2D()). It only has to be done once until you are really modifying your image.