问题描述:
之前我们创建了一个简单的窗口。但是存在这一个问题,我们创建窗口的时候创建了一个正方形,在窗口中绘制一个正方形,所以窗口中的正方形可以正常显示。(如下图)
但是当我们拉伸窗口,将窗口变为长方形的时候,发现图形中的正方形也跟着变成了长方形。(如下图)
这并不是我们想要的结果,我们希望无论窗口怎么变化,绘制的图形都不会改变。下面我们就想想为什么拉伸窗口时图形会变形?
这个画布的大小可以和窗口大小相等,也可以不相等。在上面提到的情况就是画布大小和窗口的大小相等的情况,所以正方形发生了形变。那么,如果我们可以在窗口变化之后,仍然保持画布是一个正方形,那么我们画的内容就不会形变了。
OpenGL为我们提供了一个设置这个“画布”(视口)大小的函数,即为void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
其中x,y表示视口(画布)左下角的坐标,width,height表示视口(画布)的宽和高。注意,这里的视口左下角坐标(0,0)对应的是窗口的左下角,x轴正方向向右,y轴正方向向上。
我们在原来程序的基础上增加一个回调函数:
glutReshapeFunc(redraw);
并实现void redraw(int x, int y)函数。
void redraw(int x, int y)
{
int dis = x > y ? y : x;
glViewport(0, 0, dis, dis); //创建一个视口
}
这里我们用临时变量dis记录变换窗口的较小的边,并在将视口(画布)调节成一个正方形,这样绘制的内容就不会形变了。我们用下面的两个图来说明这个过程:
我将画布设置为整个窗口大小,颜色为蓝色。可以看出来,画布的大小开始时就是窗口的大小。
接着我改变窗口大小,将它变窄,可以预测到画布被修改为一个以窗口较窄边为长度的正方形。如下图:
图中的蓝色部分就是新的画布大小,而灰色是窗口中没有用的部分。因此在这个蓝色部分中所绘制的正方形还是正方形。
源码如下:
/*
*OpenGL学习02
*程序功能:在之前的基础上添加视口,可以改变窗口的大小
*/
#include <gl\glut.h>
void draw()
{
glClearColor(0.6, 0.6, 0.6, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glRectf(-0.5, -0.5, 0.5, 0.5);
glFlush();
}
void redraw(int x, int y)
{
int dis = x > y ? y : x;
glViewport(0, 0, dis, dis); //创建一个视口
/*
*x,y表示视口左下角的坐标,width,height表示视口的宽度和高度
*这里选择大小改变后的窗口较小的边,作为新的视口的变长
*/
}
void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(600, 600);
glutCreateWindow("有视口的窗口");
glutDisplayFunc(draw);
glutReshapeFunc(redraw);
glutMainLoop();
}
原窗口如下图:
修改窗口后的效果如图:
可以看出绘制的正方形不会形变。
为了进一步了解glViewport函数,我们进一步修改程序。
OpenGL中我们可以通过glViewport函数,轻易的实现多窗口,即设立多个视口,并在每个视口中绘制不同的内容。
我们现在将窗口拆分成四个视口,四个视口分别的绘制一个颜色不同,大小和视口大小相等的正方形,来进一步掌握视口。
glColor3f(1.0, 1.0, 1.0);
glViewport(0, 0, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);glColor3f(1.0, 0.0, 0.0);
glViewport(0, 200, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);glColor3f(0.0, 1.0, 0.0);
glViewport(200, 0, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);glColor3f(0.0, 0.0, 1.0);
glViewport(200, 200, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);
上述代码中先设置一个颜色,然后设置视口大小,再绘制正方形。因为OpenGL的坐标是:坐标原点在中心,从-1~1。所以上述代码中绘制正方形的大小是视口大小。
效果图如下:
源代码如下:
/*
*OpenGL学习02
*程序功能:在之前的基础上添加视口,可以改变窗口的大小
*/
#include <gl\glut.h>
void draw()
{
glClearColor(0.6, 0.6, 0.6, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glViewport(0, 0, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);
glColor3f(1.0, 0.0, 0.0);
glViewport(0, 200, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);
glColor3f(0.0, 1.0, 0.0);
glViewport(200, 0, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);
glColor3f(0.0, 0.0, 1.0);
glViewport(200, 200, 200, 200);
glRectf(-1.0, -1.0, 1.0, 1.0);
glFlush();
}
void redraw(int x, int y)
{
int dis = x > y ? y : x;
glViewport(0, 0, dis, dis); //创建一个视口
/*
*x,y表示视口左下角的坐标,width,height表示视口的宽度和高度
*这里选择大小改变后的窗口较小的边,作为新的视口的变长
*/
}
void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(400, 400);
glutCreateWindow("有视口的窗口");
glutDisplayFunc(draw);
glutReshapeFunc(redraw);
glutMainLoop();
}
希望通过上述可以帮助理解glViewport函数。