本文使用的是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()都发生了改变,即摄像机中显示的大小发生了改变.如下图所示:
然后再洗的时候,由于洗的大小(glViewport())跟拍的一样,故不需缩放,将其直接贴在窗口(与相框)上.
(3)前面的(1)(2)中调用了用户自定义的reshape(),此处如果不调用reshape(),即窗口大小改变后交由glut系统处理,即在B处添加注释:
glutReshapeFunc(reshape);//---------(B)
则正方形大小会随窗口大小的改变而改变,正方形中心位于窗口中心,且长,宽均为窗口的一半(正方形的边长为1:[-0.5,0.5],而glut窗口的值为[-1,1]中,故是一半),故可能变为长方形.