窗口
:即屏幕中的某一个窗口,可放大放小和移动关闭。视口
:即在窗口中可以见到或可以用来绘图的部分。一般设置视口等于窗口。视景体(裁剪可视区)
:是指成像景物所在空间的集合,它是一个空间集合体。可以把它想象成一个房间,在这个可显示区域内的一切物体都可以被显示。也就是说视景体会在三维空间中裁切一部分,允许其中裁下来的部分经过投影变换后在视口内可见。整个视景体的三维坐标将完全映射到整个视口的二维坐标上投影变换
:定义一个视景体,并把它按仿射投影或正射投影形式投射到二维的视口上,投影的方式会影响视景体的类型。裁剪出的可视部分可以在视口上显示出来参考:OpenGL投影变换:视景体及glFrustum、gluPerspective 与glOrtho、gluOrtho2D
还记得上次看过的画图程序吗?OpenGL(2) ->第一个程序
这个程序里简单地通过显示回调函数,程序如下
#include
//显示回调函数
void myDisplay()
{
glClearColor(0.0, 0.0, 1.0, 0.0); //设置颜色缓冲为蓝色
glClear(GL_COLOR_BUFFER_BIT); //根据颜色缓冲给整个窗口涂色
glColor3f(1.0, 0.0, 0.0); //绘制颜色Red
glBegin(GL_LINE_LOOP); //开始绘图(封闭线段模式)
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glVertex2f(-0.5, -0.5);
glEnd(); //结束绘图
glFlush(); //立即显示
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv); //对GLUT进行初始化
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //显示方式为 单缓冲 RGB色彩
glutInitWindowPosition(100, 100); //窗口(左上角)位置
glutInitWindowSize(400, 400); //窗口尺寸(单位为像素)
glutCreateWindow("第一个OpenGL程序"); //窗口标题
glutDisplayFunc(&myDisplay); //显示回调函数
glutMainLoop();
return 0;
}
上次并没有说明关键点的坐标系统,所以大家可能不太清除为什么要把坐标定义为glVertex2f(-0.5, 0.5);
这样的值
这个绘图程序的显示效果是这样的
可以看到,当窗口为默认的正方形时,显示正常;但当窗口尺寸比例变换时,显示的正方形也跟着变了,要是希望不管窗口怎么变化,显示的正方形都保持正方,该怎么做呢?
(1) 一共有四个投影函数glFrustum、gluPerspective 与glOrtho、gluOrtho2D,它们将定义不同类型的视景体(裁剪可视区),前两个用于透视投影,后两个用于正射投影。
(2)对于本例这种二维情况,应使用正射投影,关键步骤有以下几个
glMatrixMode(GL_PROJECTION); //选定投影矩阵为当前矩阵,告诉OpenGL接下来要进行投影变换
glLoadIdentity(); //重置当前矩阵
(3)关于视图矩阵
glVertex2f(-0.5, 0.5)等
,可以使正方形居中显示 glMatrixMode(GL_MODELVIEW); //选定视图矩阵为当前矩阵
glLoadIdentity(); //重置当前矩阵
#include
//显示回调函数
void myDisplay()
{
glClearColor(0.0, 0.0, 1.0, 0.0); //背景blue
glClear(GL_COLOR_BUFFER_BIT); //根据颜色缓冲涂色
glColor3f(1.0, 0.0, 0.0); //线Red
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); //指定绘图时的坐标系统,分别是x,y,z的最小、最大值
glBegin(GL_LINE_LOOP); //开始绘图(封闭线段模式)
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glVertex2f(-0.5, -0.5);
glEnd(); //结束绘图
glFlush(); //立即显示
}
//缩放回调函数
//当窗口放缩时,要重新进行坐标映射(重新定义剪裁区域),如果没有这个,放缩后图像会变形
void changeSize(GLsizei w,GLsizei h)//GLsziei 看作 int
{
if (h == 0) //防止除0
h = 1;
GLfloat scale = (GLfloat)w /(GLfloat)h; //窗口协调比例
glViewport(0, 0, w, h); //设置视口为整个窗口
//设置坐标系统
glMatrixMode(GL_PROJECTION); //重置投影矩阵,告诉OpenGL接下来做投影变换
glLoadIdentity();
//等比例修改剪裁区域
if (w < h)
glOrtho(-1.0, 1.0, -1.0 / scale, 1.0 / scale, -1.0, 1.0);
else
glOrtho(-1.0*scale, 1.0*scale, -1.0 , 1.0, -1.0, 1.0);
//告诉openGL未来的转换将影响绘制的图形
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv); //对GLUT进行初始化
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //显示方式为 单缓冲 RGB色彩
glutInitWindowPosition(100, 100); //窗口(左上角)位置
glutInitWindowSize(400, 400); //窗口尺寸(单位为像素)
glutCreateWindow("第一个OpenGL程序"); //窗口标题
glutDisplayFunc(&myDisplay); //显示回调函数
glutReshapeFunc(&changeSize); //窗口放缩回调函数
glutMainLoop();
return 0;
}
再回顾一下几个重要的函数