屏幕坐标系
当我们在三维图形学中谈论"点(point)"时,我们常说"顶点(vertex)"。一个点有三个坐标:X, Y, Z。如何想象这三个坐标呢?
这里有一个形象的方法:使用右手定则
- X 是你的拇指
- Y 是你的食指
- Z 是你的中指。如果你把你的拇指指向右边,食指指向天空,那么中指将指向你的背后。
我们的观察方向是Z轴负半轴的方向。
为了将物体的三维坐标转换为屏幕上的像素位置,需要以下3个步骤:
1.变换
包括视图(视点)变换、模型变换和投影变换。都是由矩阵乘法表示。
这些操作中包括旋转,移动,缩放,反射,正投影和透视投影等。一般情况下,需要组合使用几种变换。
2.剪裁
场景是在一个矩形窗口中渲染的,位于窗口之外的部分就要丢掉。
3.视口变换
视口变换,就是将经过变换的坐标和屏幕像素之间建立对应关系的过程。
变换
视图(视点)变换:
相当于照相机(眼睛)的位置,要对准场景。函数gluLookAt()来指定视图变换,这函数有9个参数,前3个表示照相机(眼睛)的位置,中间3个表示我们要瞄准哪个方向,后3个表示哪个是朝上的向量。
模型变换:
对被拍摄的模型的各种变换操作。包括各种模型变换函数,glScalef(), glTranslatef()等。注意,我们可以不通过移动照相机(视图变换)来观察一个立方体,而是移动这个立方体(模型变换)。
模型视图矩阵(modelview martrix):模型变换和视图变换的组合。
投影变换:
a.确定视野(视景体),即确定哪些物体位于视野之内,以及它们被看到的程度。
b.除了视野,投影变换还决定物体是如何投影到屏幕上。两种投影类型:透视投影(perspective projection)和正投影(orthographic projection)
透视投影:
类似于日常生活看到的场景,远处物体看起来小,近处看起来大。使用透视投影函数glFrustum()和gluPerspective().
glFrustum(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far)
far, near是指近裁剪面,远剪裁面离视点的距离(>0),
对角坐标, (left, bottom, -near)和(right, top, -near)定义了近裁剪面的左下角和右上角的(x, y, z)坐标。
gluPerspective(GLdouble fovy, GLdouble aspect,
GLdouble near, GLdouble far)
fovy视角,aspect = w/h。
正投影:
把物体直接映射到屏幕上,不影响它们的相对大小。也就是图像反映物体的实际大小,而不是它们看上去的样子。
函数glOrtho()创建一个用于正交投影的平行视景体, 将其与当前矩阵相乘。
void glOrtho(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far);
void glOrtho2D(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top);
视口变换
投影变换和视点变换一起决定了场景的映射方式,而视口变换指出了场景被映射到什么样的屏幕区域,即指定场景在屏幕上所占据的区域。可以这样认为:视口变换定义处理后照片的大小和位置, 你希望照片像海报那么大还是钱包那么大。
函数glViewport(0.0, 0.0, (GLsizei) w, (GLsizei) h)有4个参数,前2个参数描述窗口内部有效屏幕空间的原点(0, 0); 后2个参数描述有效区域的width和height(均以像素为单位)。
绘制场景
指定了所有的变换后,就可以进行绘制场景了。
a. 通过模型变换和视图变换对场景中得每个物体的每个定点进行变换;
b. 根据指定的投影变换对每个顶点进行变换;
c. 如果顶点位于视景体(视野)之外,则进行剪裁;
d. 经过变换的剩余顶点除以w, 然后映射到视口中。