In OpenGL, how can I adjust for the window being r

2020-02-09 10:34发布

问题:

I am drawing several shapes (such as circles) that are keyed off of the window height & width. Since the window always starts at a given size, they are drawn correctly, but when the window is resized, it messes the aspect ratio up.

How can I draw the shapes properly, regardless of window size?

回答1:

You definitely don't want to make the size of your objects explicitly dependent on the window size.

As already suggested by genpfault, adjust your projection matrix whenever the window size changes.

Things to do on window resize:

  1. Adjust viewport

    glViewport(0, 0, width, height)
    
  2. Adjust scissor rectangle (only if you have GL_SCISSOR_TEST enabled)

    glScissor(0, 0, width, height)
    
  3. Adjust projection matrix

    In case of legacy (fixed function pipeline) OpenGL, you can do it the following ways:

    glFrustum(left * ratio, right * ratio, bottom, top, nearClip,farClip)
    

    or

    glOrtho(left * ratio, right * ratio, bottom, top, nearClip,farClip)
    

    or

    gluOrtho2D(left * ratio, right * ratio, bottom, top)
    

    (assuming that left, right, bottom and top are all equal and ratio=width/height)



回答2:

If you're using something like gluPerspective() just use the window width/height ratio:

gluPerspective(60, (double)width/(double)height, 1, 256);


回答3:

You should setup some sort of window handler function that is called whenever your OpenGL window is resized. You need to take care of the case when aspectRatio > 1, and when aspectRatio <= 1 separately. Not doing so may result in geometry falling offscreen after a screen resize.

void windowResizeHandler(int windowWidth, int windowHeight){
    const float aspectRatio = ((float)windowWidth) / windowHeight;
    float xSpan = 1; // Feel free to change this to any xSpan you need.
    float ySpan = 1; // Feel free to change this to any ySpan you need.

    if (aspectRatio > 1){
        // Width > Height, so scale xSpan accordinly.
        xSpan *= aspectRatio;
    }
    else{
        // Height >= Width, so scale ySpan accordingly.
        ySpan = xSpan / aspectRatio;
    }

    glOrhto2D(-1*xSpan, xSpan, -1*ySpan, ySpan, -1, 1);

    // Use the entire window for rendering.
    glViewport(0, 0, windowWidth, windowHeight);
}


回答4:

I am learning opengl too. I faced this problem yesterday and I have not found the correct answer. Today, I have solve the problem. In my little program, the object changes size when resizing the window changing width or heigt. This is my code (please, forgive my errors):

#include <GL/freeglut.h>

void fnReshape(int ww, int hh)
{
  GLdouble r;
  if(hh == 0)
    hh = 1.0;
  if(hh > ww)
    r = (double) hh / (double) ww;
  else
    r = (double) ww / (double) hh;
  glViewport(0, 0, ww, hh);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if(hh > ww)
    glFrustum(-1.0, 1.0, -1.0 * r, 1.0 * r, 2.0, 200.0);
  else
    glFrustum(-1.0 * r, 1.0 * r, -1.0, 1.0, 2.0, 200.0);
}
//////////////////////////////////////////////////////////////////
void fnDisplay(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(0., 0., -5.);
  glBegin(GL_QUAD_STRIP);
  glColor3f(0., 0., 1.0);
  glVertex3f(-1., -1., 0.);
  glVertex3f(-1., 1., 0.);
  glVertex3f(1., -1., 0.);
  glVertex3f(1., 1., 0.);
  glEnd();
  glutSwapBuffers();
}
////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA |GLUT_DOUBLE);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Sample window");
    glClearColor(1.0, 0, 0, 1.0);
    glutDisplayFunc(fnDisplay);
    glutReshapeFunc(fnReshape);
    glutMainLoop();
    return 0;
}


回答5:

There are many methods to do that. Following example shows you how I'm doing it in my projects and its working. The example shows you simply a rectangle box which do not changes it size when window is resizing. You can directly copy and paste it in your project(consider that i'm a openGl beginner)

#include<windows.h>
#include<glut.h>

GLfloat x1=100.0f;
GLfloat y1=150.0f;
GLsizei rsize = 50;

GLfloat xstep=1.0f;
GLfloat ystep=1.0f;

GLfloat windowWidth;
GLfloat windowHeight;


void scene(void){
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(1.0f,0.0f,0.0f);

   glRectf(x1,y1,x1+rsize,y1-rsize);

   glutSwapBuffers();
}

void setupRc(void){

  glClearColor(0.0f,0.0f,1.0f,0.0f);

}

void changeSize(GLsizei w,GLsizei h){
  if(h==0)
  h=1;
  glViewport(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
   if(w>=h){
     windowWidth=250.0f*w/h;
     windowHeight=250.f;
   }
   else{
     windowWidth=250.0f;
     windowHeight=250.f*h/w;
   } 

   glOrtho(0.0f,windowWidth,0.0f,windowHeight,1.0f,-1.0f);


   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();


}




void main(void){

   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);

   glutCreateWindow("Rectangle");

   glutReshapeFunc(changeSize);
   glutDisplayFunc(scene);
   setupRc();

   glutMainLoop();

}