三维观察
如果对比纹理映射和以前的代码,发现多了调用gluLookAt方法语句,如下图所示。
如果没有这条语句,窗口里什么都没有。这其中涉及到三维观察或者变换管线,而三维观察的设置在OpenGL编程中非常重要的。变换管线的处理流程如下图。
类比到我们现实生活 理解上图的意思。如果我们要观察一个物体,我们可以从不同的位置去观察它(视图变换);移动或者旋转它(模型变换);如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果(投影变换);我们可能只希望看到物体的一部分,而不是全部(剪裁);我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部(视口变换)。
模型视图变换
上图中输入(初始化顶点数据)是在模型坐标(或局部坐标)中得到的,相对于世界坐标。该位置要经过模型变换才能得到世界坐标系的位置,关系如下:
模型坐标系中的点Pm可以通过下面公式获得在世界坐标系中的位置。
不同位置观察物体,决定了采用哪种视图坐标系(或者叫相机坐标系)。下面公式计算世界坐标系的点在视图坐标系中的位置。
变换示意图如下。在OpenGL中,模型变换和视图变换是在GL_MODELVIEW状态下一起设置的。任何对相机位置和方向的改变都要更新模型视图矩阵。
gluLookAt(eye.x, eye,y, eye.z, look.x, look.y, look.z, up.x, up.y, up.z)就是设置视图坐标系的,参数是相对于世界坐标而言。如果没有调用gluLookAt(),那么照相机就被设置为默认的位置和方向。在默认情况下,照相机位于原点,指向z轴的负方向,朝上向量为(0,1,0)。
投影变换
投影变换将在模型视图变换之后应用到顶点上。这种投影实际上定义了视景体并创建了裁剪平面。投影一般分为正投影和透视投影。正投影大多在进行2D绘制使用。glOrtho(left, right, bottom, top, near, far)创建一个平行六面体的视景图,它在x方法上从left到right延伸,在y方向上从bottom到top延伸,在z方向上从near到far延伸。
透视投影所显示的场景与现实生活中更加接近,远处的物体看起来比近处同样大小的物体更小些。
设置视景体可以使用gluPerspective 和glFrustum,二者都能达到相同的效果。下图中,两个蓝色平面之间为可见区域,如果物体不在两平面之间,在软件里是看不见该物体。另外函数的参数是相对于视图坐标而言的。
gluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal);
视口变换
当我们得到了一个场景的二维投影,它将被映射到屏幕上某处的窗口上。这种到物理窗口的映射是我们最后要做的变换,称为视口变换。在OpenGL使用下面函数进行设置。
glViewport (GLint x, GLint y, GLsizei width, GLsizei height)
对于二维绘图而言,世界窗口由函数gluOrtho2D()设置,它的原型是
void gluOrtho2D(GLdouble left, GLdouble right, GLdouble buttom, GLdouble top);
对于三维情况,视口的设定通过glViewport()函数,它的原型是:
void glViewport(GLint x, GLint y, GLint width, GLint height);
设置视口的左下角,以及宽度和高度。