一. 视景体
视景体是指成像景物所在空间的集合。它是一个空间集合体。
注意视景体指的是一个空间集合。一般来说,集合中的每个空间都是个立方体。然后所有的这些空间堆在一起,在外侧取一个最大的外接立方体,就是可显示的区域,该可显示区域也是一个视景体。在这个可显示区域内,放置着可以显示的物体。注意,可以显示的物体仅仅是拥有显示权限,但是不一定显示,这取决于相机等其他因素。
单个的视景体,比如一个球体,若要完全显示,其视景体应该是该球体的最小外接立方体;若要只显示上半部分,则取上半球,其视景体是上半球的最小外接立方体。对于半球而言,上半球是视景体,那么其只有上半球有显示权限,下半球没有,所以就算是将该球体位置拉远,也只能看到上半球。
比如一个球体,视景体为该球体的最小外接立方体。可以这样理解:该视景体的内容完完全全绘制在一张大小正好的画布上,画布以外都是背景色,取黑色。然后摄像机刚好看着这张画布,画布上的内容完全显示在摄像机屏幕上。接着,对摄像机进行了右移,在摄像机的画面上,左侧是画布上的部分内容,右侧是黑色背景色。也就是说此时立方体虽然有显示权限,但是却并没有完全显示。但未显示的部分依然是有显示的可能的。
若视景体仅仅为上半球,那么默认情况下,上半球所映射的画布刚好充满摄像机。将摄像机下移,则摄像机画面中显示的是上半球切面的水平线,水平线以下是黑色背景色。即使此时从理论上来说摄像机对着下半球,但由于视景体仅为上半球,所以下半球是没有显示权限的,是不会被显示的。
对OpenGL而言,视景体就意味着可显示空间,在该空间内的一切物体都可以被显示,都可以被看到,该空间外的一切物体都不能被看到。相机若要看到该空间中的物体,则相机本身就必须处于该视景体空间中。若相机在视景体空间外,哪怕该视景体就在相机正对的面前,相机依然无法看到。
二. 投影变换
投影变换的任务有两个:①选择需要显示的视景体②将三维视景体以某种投影方式映射为二维图像。
所以,投影变换的目的就是定义一个视景体,使得视景体外多余的部分裁剪掉,最终进入图像的只是视景体内的有关部分。
投影包括透视投影(PerspectiveProjection)和正视投影(Orthographic Projection)两种。
根据这两种投影方式的不同,映射出的二维图像也不同:透视投影会出现近大远小的透视效果;正视投影不会影响物体的相对大小,即同样长的边,在远处与在近处看到的长度是相同的。
三. 投影函数:glFrustum、gluPerspective 与glOrtho、gluOrtho2D
OpenGL共有4个投影函数,其中有2个是透视投影函数,2个是正投影函数。
1. 透视投影函
透视投影函数有两个:glFrustum、gluPerspective
① glFrustum
voidglFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdoublenear,GLdouble far);
glFrustum创建一个透视视景体。这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的Z负值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值。
② gluPerspective
voidgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);
gluPerspective创建一个对称透视视景体,但与glFrustum不同,参数fovy定义视野的角度,以z轴为中心向两侧平分,范围是[0.0, 180.0],也就是说最大为上下各90°;参数aspect是投影平面宽度与高度的比,或者说是视景体的宽高比;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。
以上两个函数缺省时,视点都在原点,视线沿Z轴指向负方向。
2. 正投影函
透视投影函数有两个:glOrtho、gluOrtho2D
① glOrtho
void glOrtho(GLdouble left,GLdoubleright,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
这个函数描述了一个平行修剪空间,或者说是一个平行立方体。这种投影意味着离观察者较远的对象看上去不会变小(与透视投影相反)。在3D笛卡尔坐标中想象这个修剪空间,左边和右边是最小和最大的X值,上边和下边是最小和最大的Y值,近处和远处是最小和最大的Z值。正射投影,又叫平行投影。这种投影的视景体是一个矩形的平行管道,也就是一个长方体。正射投影的最大一个特点是无论物体距离相机多远,投影后的物体大小尺寸不变。也就是说,一个处于3D空间中的长方体,人眼看到的应该是近大远小。但使用glOrtho函数进行投影,则远近大小相同。
也就是说,glOrtho会指定一个空间,然后该空间就是可显示的区域。该空间区域内的所有视景体,包括被该空间完全包含的以及被该空间边界所切开并包含在空间内的,都拥有显示权限。
如上图所示,暂时只考虑x、y轴情况:
a) 若glOrtho(-2,2,-2,2,10,10),则绿色部分拥有显示权限,默认绿色部分会填满整个显示区域。即使平移摄像机,蓝色的部分也不会被显示
b) 若glOrtho(-4,4,-4,4,10,10),则蓝色部分拥有显示权限,默认蓝色部分会填满整个显示区域
注意,在默认情况下(未对摄像机等进行修改),屏幕上的某个矩形区作显示区域,其大小使用像素单位,且整个显示过程中宽高不会改变,那么:一旦调用①与②,整个矩形显示区域都会被填满,所以看起来好像调用②的时候对显示内容进行了缩小一样。
z轴情况同理。
最后,注意glOrtho仅用于选取一个拥有显示权限的区域,而不负责显示。
② glOrtho
voidgluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)
gluOrtho2D是一个特殊的正射投影函数,主要用于二维图像到二维屏幕上的投影。它的near和far缺省值分别为-1.0和1.0,所有二维物体的Z坐标都为0.0。因此它的裁剪面是一个左下角点为(left,bottom)、右上角点为(right,top)的矩形。
示例:
假设有一个球体,半径为1,圆心在(0, 0, 0),那么:
① glOrtho(-1.5, 1.5, -1.5, 1.5,-10, 10);表示用一个宽高都是3的立方体把球体整个装了进来
② glOrtho(0.0, 1.5, -1.5, 1.5,-10, 10);表示用一个宽是1.5,高是3的立方体把球体整个的右面装进来
③ glOrtho(0.0, 1.5, 0.0, 1.5,-10, 10);表示用一个宽和高都是1.5的立方体把球体的右上角装了进来
上述三种情况可以见图: