上节主要提到了观测变换 (Viewing transformation), 其中包括了视图变换和投影变换。所谓的视图变换就是利用摄像机和物体的相对位置关系,始终把摄像机从任意一个位置移动到经典的原点位置,看向-z,并且向上方向是+y。并且保持其他物体和摄像机一样的移动。此时,我们就可以得到所有的物体都是由一个标准位置的相机看过去的,此时我们要做的就是把它从三维投影到二维。投影分为正交投影和透视投影。
区别:
在各种观测变换完了之后,场景里的所有物体都会被变换到-1到1的三次方这样一个经典的立方体里面,那下一步是什么?那这就引出了这节的光栅化的内容(其实就是把立方体里的内容画在屏幕上)。那该如何光栅化,怎么画呢?
首先对于上节课,还有一个剩余内容。在正交投影里,我们需要六个值(上下左右远近),也就是x,y,z的覆盖来定义立方体。那对于透视投影,除了假设中已有的n和f,我们还需要哪些信息来定义一个视锥(frustum)呢?
aspect ratio = width / height 宽高比
vertical field-of-view (forY)垂直可视角度
有了这两个概念,我们就利用这些值来求出近面的高度和宽度,那当然也就可以进一步计算出正交投影中的六个值(上下左右远近)
那回过来,在MVP做完了之后
Model transformation(placing objects)
View transformation(placing camera)
Projection transformation
那么在这三步做完了之后,所有的物体都会被转化到经典的-1 到 1 的立方这个立方体里面去,最后要把这个画在哪里呢?
答案当然是屏幕上。
首先来看,对于图形学,什么是屏幕呢?
是一个二维的数组,数组中的每一个元素是一个像素。屏幕是一个典型的光栅成像设备。而所谓的Raster其实就是德语里屏幕的意思,而Rasterize光栅化,就是把东西画在屏幕上。所以把东西画在屏幕上的过程就是光栅化的过程。
那对于像素呢,像素(pixel is the short for “picture element”)在我们这门课中认为其是一个小方块,且块中内部的颜色是完全相同的,即最小单位,我们用256个等级0-255来表示灰度,同时可以用rgb三个值来定义颜色。
那定义完屏幕,我们再定义一下屏幕空间。
其实就是一个坐标系。本课中将坐标原点定义在左下角,用(x,y)(x、y 为整数)这样的形式来定义一个像素,像素下标从(0,0)到(width - 1,height - 1)。且(x,y)像素的中心在(x + 0.5, y + 0.5)。屏幕范围从(0,0)到(width,height)
那回过来,我们本来是要干什么呢?我们有一个-1到1的三次方的立方体,要把它转化到屏幕上,那自然就要做从-1到1三次方到屏幕(0到width乘以0到height)这么一个空间的变换。
首先,三维到二维,我们需要先去掉一个维度,那对于z轴,我们先忽略,z的用途之后再说。然后对于x、y,将其从-1,1^2 拉到[0,width]x[0,height]就简单了,用一个如下的转换矩阵。
此处这个变换叫做视口变换。就相当于把这个-1到1的平方转换到屏幕空间。
那么到这一步,不管我们之前是通过aspect和宽高比定义的frumstum还是通过正交投影的立方体,我们都已经变换到-1 到1 的三次方了,且现在我们已经把它的xy放在屏幕上了,那现在我们就相当于已经得到了一张场景的虚拟照片了。
下一步就是把图打撒成像素,真正的画在屏幕上。这也就是所谓的光栅化。
不同的光栅显示设备:
这页是讲到现在的显示设备都是通过内存中的一块区域来映射到屏幕上。
现在的主要显示设备还是平板显示设备:LCD液晶显示器。
这里是简单介绍了一下液晶的显示原理。液晶通过自己的不同排布影响光的偏振方向来决定一个像素显示什么。
LED发光二极管显示设备,墨水屏(刷新率很低)等等。
那现在回到我们的主线,如何在这么多的成像设备上画东西。假设还是如上,屏幕是由像素构成的,像素的颜色一致的方块。
首先,在光栅化操作中,我们常用三角形来组成其他三维空间,二维空间中的图形。为什么我们常用三角形呢?
接下来就是在已有三角形在屏幕上的位置信息之后,我们该如何确定逼近这个三角形的像素点集合。这个就是光栅化中重要的一个概念,判断一个像素和三角形的位置关系。更确切的是,我们考虑像素的中心点和三角形的位置关系。
一个简单的做法来做光栅化,就是采样。
此处的采样是指用一个连续的函数,去遍历每一个位置,看函数值是多少。这相当于是把一个函数离散化的过程。
那对于我们此处这个例子中,我们要判断像素中心是否在三角形内,即下面这个函数的函数值到底是1还是0。
那要如何做呢,还和上面一样,考虑所有的像素中心,遍历全屏幕。
采样过程是这样,那具体判断函数该如何实现?
用三次向量的叉积来实现。从而也就可以确定对于每个像素要不要填上颜色。另外要注意对于边上的点,要么不处理要么特殊处理,自己定义就行,没有关系。
刚才我们提到的这个是通过采样来做光栅化的过程,那在这个过程中,还可以有一些简化的操作。如,刚才是对整个屏幕的检查,我们可以简化到不同坐标下最小值到最大值的检查,这样可以简化一点计算量。那我们称这个蓝色区域为包围和,这个严格叫轴向的包围和,X-alied bounding box ,缩写为aabb。
甚至对于一些特殊情况,还可以考虑采用对每一行选取最大最小边界来限制采样范围,这样的方法使用于于窄长且有一定旋转角度的三角形。
但是这样的采样方式会导致锯齿的结果(走样),那原因就是因为像素本身有一定的大小,并且由于采样率对于信号的频率是不够高的,所以就导致了信号的走样问题。