opengl 相机 视口 详解

本文使用的是glut:

#include "stdafx.h"

#include <GL/glut.h>

 

void init(void)

{

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

}

void display(void)

{

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0f,0.0f,0.0f); 

 

    glLoadIdentity();

    glTranslatef( 0.0f, 0.0f , -1.0f);

 

    //draw a square

    glBegin( GL_QUADS);

   

       glVertex3f(  0.5f,  0.5f, 0.0f);

       glVertex3f( -0.5f,  0.5f, 0.0f);

       glVertex3f( -0.5f, -0.5f, 0.0f);

       glVertex3f(  0.5f, -0.5f, 0.0f);

 

    glEnd();

 

    glFlush();

}

void reshape(int w,int h)

{

    static bool bFirst= true;//---------(A1)

    if ( !bFirst)

    {

       return;

    }

    bFirst= false; //---------(A2)

 

    glViewport(0,0  ,(GLsizei)w  ,(GLsizei)h  );

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    gluPerspective( 90.0f, (GLfloat)w/ (GLfloat)h, 0.1f, 1000.0f );

 

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

int main(int argc, char** argv)

{

    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutInitWindowSize(450,450);

    glutInitWindowPosition(200,200);

    glutCreateWindow("Hello");

    init();

    glutDisplayFunc(display);

    glutReshapeFunc(reshape);//---------(B)

    glutMainLoop();

    return 0;

}

其实Opengl的三维物体显示流程可以这样看:

先根据gluPerspective()指定的视锥体,用照相机来拍照(拍照的时候你可以看到相机中显示的画面,该画面即为视锥体投影平面, 如果gluPerspective()不变,即用相机拍到的照片的内容也不变),拍照完成后会得到一张照片(电子照片,还未洗出来).

要想用户看到三维结果(即看到洗出来的照片),可能会将电子照片进行缩放(大小为glViewport()设置的大小,即第3,4个参数:长为width,宽为height),然后洗照片,照片洗出来后,将其贴在相框(即用户的WINDOWS窗口)(照片的左下角顶点在glViewport()的前二个参数(x,y),照片可能并未完全占满相框,所以可以把几张洗出来的照片贴在相框上,即实现多视图),此时的相框即是我们最后看到的结果.如下图所示:

 

(1)以上程序会调用自定义的reshape(),但只调用一次.初始时会在屏幕正中央看到一个正方形.当改变窗口大小时,会看到该正方形大小不变,原因如下:因为reshape()只调用了一次,当改变窗口大小时, gluPerspective()没变,即用相机拍到的照片不变,视口也没变化,即用户看到的始终是一个正方形,此时窗口大小(即相框)发生了变化,但这个照片仍是初始那么大,然后该照片贴在窗口左下角(照片左下角与窗口左下角重合).

(2)如果将reshape()中的A1---A2去掉,即回归正常:

void reshape(int w,int h)

{

    glViewport(0,0  ,(GLsizei)w  ,(GLsizei)h  );

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    gluPerspective( 90.0f, (GLfloat)w/ (GLfloat)h, 0.1f, 1000.0f );

 

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

则会看到正方形仍在屏幕中间,但大小可能会发生改变((1)中的正方形大小不变).第一次看到的肯定是正方形,而且在中央;而当窗口大小改变时, gluPerspective()glViewport()都发生了改变,即摄像机中显示的大小发生了改变.如下图所示:

 opengl 相机 视口 详解_第1张图片

 

然后再洗的时候,由于洗的大小(glViewport())跟拍的一样,故不需缩放,将其直接贴在窗口(与相框).

(3)前面的(1)(2)中调用了用户自定义的reshape(),此处如果不调用reshape(),即窗口大小改变后交由glut系统处理,即在B处添加注释:

glutReshapeFunc(reshape);//---------(B)

则正方形大小会随窗口大小的改变而改变,正方形中心位于窗口中心,且长,宽均为窗口的一半(正方形的边长为1:[-0.5,0.5],glut窗口的值为[-1,1],故是一半),故可能变为长方形.

你可能感兴趣的:(opengl 相机 视口 详解)