3.1 简介:用照相机打比方

来源:互联网 发布:aws s3 php 编辑:程序博客网 时间:2024/06/15 02:41

开始第3章的学习啦。这一章,很重要的。主要讲解视图,讲OpenGL将物体描述呈现在屏幕上的整个过程。

这个成像的过程,有点像照相机照相:
1. 把照相机固定在三脚架上,并让它对准场景(视图变换)。
2. 对场景进行安排,使各个物体在照片中的位置是我们所希望的(模型变换)。
3. 选择照相机镜头,并调整放大倍数(投影变换)。
4. 确定最终照片的大小。例如,我们很可能需要把它放大(视口变换)。

整个过程中,讲述了4个主要步骤,每个步骤对应一个变换,4大变换分别是视图变换,模型变换,投影变换和视口变换。其中视图变换必须出现在模型变换之前,但是可以在绘图之前的任何时候执行投影变换和视口变换。

视图、模型和投影变换,是通过矩阵乘法来实现的。通过创建一个4x4的矩阵M,然后把它与场景中的每个顶点v的坐标相乘,以实现变换:
v’ = Mv
顶点总是有4个坐标(x, y, z, w),但是大多数情况下w都固定为1。对于二维数据,z总是为0。

视图变换 和 模型变换的变换矩阵,放在一起,形成了模型视图矩阵。这个矩阵作用于物体坐标,产生视觉坐标。具体坐标变换流程见下图。
这里写图片描述

这里写图片描述
上面两张图片,摘抄自不同的书,但是它们描述的流程都是一样的,讲解了物体坐标,变换到设备坐标的过程。

MC,表示Model Coordinate, WC表示 World Coordinate, VC表示View Coordinate, PC表示 Projection Coordinate, NC表示Normalized Coordinate, DC表示 Device Coordinate。

模型变换

物体最开始的时候的坐标为MC,这个坐标,是相对于模型自身的一个坐标系,通常由物体建模时规定的,通常会将坐标原点放在物体的中心位置,至于坐标系,则看使用的建模工具导出模型的时候,采用的坐标系。

物体放置到场景中,使用的是世界坐标系,经过模型变换,可以将物体上面的所有顶点,统一变换到世界坐标系(WC)中。

视图变换

然后,摄像机放在某个位置,摄像机坐标系的中心,位于摄像机原点,坐标系通常采用左手坐标系,这样做,是因为这样的话,离我们远的物体的Z坐标较大,这样比较符合我们看东西的习惯。WC经过视图变换,坐标系转换到了视图坐标(VC)。

投影变换

视图坐标,再经过投影变换,变换到了投影坐标,这时候的坐标,从三维坐标,降到了2维坐标。投影变换有两个任务,一是确定可视范围,哪些物体可被投影到屏幕上。二是确定投影方式,是正交投影,还是透视投影。正交投影是指,物体以原始尺寸投影到屏幕上。透视投影是指,投影到屏幕上的物体,近大远小,即离观察者近的,投影面积大,离观察者远的,投影面积小。

裁剪

裁剪,是指裁剪掉位于可视范围之外的坐标点。这个可视范围,由投影区域决定。这个过程,红宝书上,和投影变换,放在了一起。
而计算机图形学中,将裁剪 和 规范化设备坐标放在了一起。

规范化设备坐标

变成了2维坐标投影后,物体的坐标范围各异。比如有的坐标范围从0~200(任取的一个指), 有的范围从0~1800(也是任取的值),而这些2维点,最终都要投影到具体屏幕上的,而各个屏幕的分辨率不同,比如有的为1024*768, 有的为1920*1080。如果一个0~200的坐标范围,直接投到屏幕上,那么只有一个很小的块,而一个0~1800的投到屏幕上,1024*768的那块屏幕都存不下,它最多也就1024。为了解决不同屏幕的分辨率不同问题,才有了将投影后的坐标进行规范化的说道。

规范化,是指统一投影坐标的范围,比如全部统一到(-1, 1)之间。这样弄完之后的坐标,如果投影到1024*768上面的话, 1可以投影到1024上,而1920*1080的屏幕的话,1可以投影到1920位置上,这样就方便很多。

视口变换

视口变换,相当于指定相片的尺寸。
视口,是指窗口上的可视区域。我们将之前的投影出来的东西,放到这个视口上去显示。
规范化坐标之后,所有像素坐标,都位于(-1, 1)之间,再投影到视口,只需要按一定的比例进行缩放,然后放到视口中就可以了。

通用的变换函数

通用的变换函数有glMatrixMode,glLoadIdentity,glLoadMatrix*, glMultMatrix*, glLoadTransposeMatrix*, glMultTransposeMatrix*。
上面6个函数,都是用来操作矩阵堆栈的。glMatrixMode用来切换矩阵堆栈,glLoadIdentity用来将当前矩阵堆栈置为单位矩阵,glLoadMatrix则用来替换当前矩阵堆栈中的矩阵, glMultMatrix*则是用一个矩阵来乘以当前矩阵堆栈中的矩阵, glLoadTransposeMatrix* , glMultTransposeMatrix*的意义和glLoadMatrix*, glMultMatrix*的意义相同,只是参数不同。OpenGL默认的矩阵是列主序的,而我们C语言写的 数组,用来表示矩阵的,是行主序的,通过这个Transpose名称的函数,就可以直接使用行主序的矩阵了。

0 0
原创粉丝点击