Lecture 5 光栅化(Rasterization)
1. 光栅化
1.1 概述
- 在进行观测变换(viewing transformation)它包含视图变换和投影变换之后就需要将变换后的三维对象在二维屏幕上显示出来,这就是光栅化的过程
- 定义透视投影的视锥
从摄像机出发看向近平面,我们可以对近平面定义一个宽度 w i d t h width width和高度 h e i g h t height height,因此宽高比可定义为 w i d t h h e i g h t \frac{width}{height} heightwidth,其表示了近平面的大小。如上图红线显示部分,我们可以定义field of view也即FOV,其表达了可以看到的视野范围,上图中分别取近平面上下 w i d t h 2 \frac{width}{2} 2width处与摄像机相连,其夹角范围表达了Vertical Field of View(fovY),即垂直方向上的可视范围,通过宽高比,我们就可以得到水平方向的可视范围。 - 将fovY转化为上节课所定义的
l
(
沿
x
负方向
)
,
r
(
沿
x
正方向
)
,
b
(
沿
y
负方向
)
,
t
(
沿
y
正方向
)
l(沿x负方向),r(沿x正方向),b(沿y负方向),t(沿y正方向)
l(沿x负方向),r(沿x正方向),b(沿y负方向),t(沿y正方向),如下图所示
其中 ∣ n ∣ \left | n \right | ∣n∣表示摄像机到近平面的具体,因此就有如下关系 tan f o v Y 2 = t ∣ n ∣ \tan \frac{fovY}{2} =\frac{t}{\left | n \right | } tan2fovY=∣n∣t,而对于宽高比可定义为 a s p e c t = w i d t h h e i g h t = 2 r 2 t = r t aspect = \frac{width}{height} =\frac{2r}{2t} =\frac{r}{t} aspect=heightwidth=2t2r=tr
1.2 将规范化的立方体变换到屏幕
- 如何定义一个屏幕?
- 屏幕可以看做是存储像素的数组
- 数组的大小表示分辨率
- 屏幕也是一个很好地光栅化成像设备
- 光栅化(Raster)可以定义为将东西画在屏幕上就是光栅化过程
- 在这里定义一个像素
- 一个像素可表示为一个小方块
- 一个像素内的颜色可以用RGB(Red,Green,Blue)来表示
- 定义屏幕空间左下角为坐标原点
(
0
,
0
)
\left ( 0,0 \right )
(0,0),然后就用像素的索引进行填充,如下图所示
其中,通过每一个像素的索引来定义像素的位置 ( x , y ) \left ( x,y \right ) (x,y), x x x、 y y y均为整型,如果屏幕空间大小为 w i d t h width width和 h e i g h t height height,则像素的索引范围为 ( 0 , 0 ) \left ( 0,0 \right ) (0,0)到 ( w i d t h − 1 , h e i g t h − 1 ) \left (width-1,heigth-1\right ) (width−1,heigth−1),而对于每一个像素方块的中心点的位置可定义为 ( x + 0.5 , y + 0.5 ) \left ( x+0.5,y +0.5\right ) (x+0.5,y+0.5),因此整个屏幕空间的覆盖范围为 ( 0 , 0 ) \left ( 0,0 \right ) (0,0)到 ( w i d t h , h e i g t h ) \left (width,heigth\right ) (width,heigth),至此,屏幕空间定义完毕。 - 屏幕空间定义完毕后,可以将观测变换的结果映射到二维屏幕上,我们首先忽略
z
z
z的大小
将 x y xy xy平面的 [ − 1 , 1 ] 2 \left [ -1,1 \right ] ^{2} [−1,1]2变换到 [ 0 , w i d t h ] × [ 0 , h e i g h t ] \left [ 0,width \right ] \times \left [ 0,height \right ] [0,width]×[0,height],先对其宽高分别缩放至 w i d t h 2 \frac{width}{2} 2width和 h e i g h t 2 \frac{height}{2} 2height,然后再将原点移动至 [ w i d t h 2 , h e i g h t 2 ] \left [ \frac{width}{2},\frac{height}{2} \right ] [2width,2height],其变换矩阵可表达为
M v i e w p o r t = [ w i d t h 2 0 0 w i d t h 2 0 h e i g h t 2 0 h e i g h t 2 0 0 1 0 0 0 0 1 ] {\Large M_{viewport} = \begin{bmatrix} \frac{width}{2} & 0 & 0 & \frac{width}{2}\\ 0 & \frac{height}{2} & 0 & \frac{height}{2}\\ 0 & 0 & 1 & 0\\ 0& 0 & 0 &1 \end{bmatrix}} Mviewport=⎣ ⎡2width00002height0000102width2height01⎦ ⎤
这就是视口变换矩阵表达式
1.3 在光栅显示器上绘制
- 为什么将三角形作为图形学最基础的形状图元
- 大多数的多边形都能够分解为三角形
- 三角形内部都是平面的,比如正方形沿着对角线进行折叠就变成三维的
- 三角形能很好地定义内部和外部(通过叉乘)
- 三角形的三个顶点定义了之后,可以很方便的在三角形内部进行插值
- 通过采样算法来实现光栅化
- 采样就是将连续的函数离散化的过程
- 因此光栅化的过程就是判断像素的中心点是否是在要显示的多边形内部的问题,如果在内部就可以填充相应的颜色,如下图所示
- 对于光栅化,我们可以定义一个这样的采样函数来判断是否在三角形内部
i n s i d e ( t , x , y ) = { 1 ( x , y ) 在三角形内部 0 其他情况 {\Large inside(t,x,y) = \begin{cases} 1&\left ( x,y \right )在三角形内部 \\ 0&其他情况 \end{cases}} inside(t,x,y)=⎩ ⎨ ⎧10(x,y)在三角形内部其他情况
可以遍历屏幕空间所有的像素点,通过 i n s i d e inside inside函数判断像素点是否在三角形内部来进行采样。 i n s i d e inside inside函数内部实现原理是什么呢?就是通过叉乘来判断一个点位于向量的哪一侧,如下图示例
其中点 Q Q Q是需要判断的像素中心点,而 △ P 0 P 1 P 2 \triangle P_{0}P_{1}P_{2} △P0P1P2即为要绘制的三角形,对于向量 P 1 P 2 → \overrightarrow{P_{1}P_{2}} P1P2而言, P 1 P 2 → × P 1 Q → \overrightarrow{P_{1}P_{2}} \times \overrightarrow{P_{1}Q} P1P2×P1Q根据右手定则为朝屏幕外,是正值,在 P 1 P 2 → \overrightarrow{P_{1}P_{2}} P1P2的左侧,同理对于向量 P 1 P 0 → × P 1 Q → \overrightarrow{P_{1}P_{0}}\times \overrightarrow{P_{1}Q} P1P0×P1Q的结果是朝向屏幕内,则表示点 Q Q Q在 P 1 P 0 → \overrightarrow{P_{1}P_{0}} P1P0的右侧,以此类推可以判断点 Q Q Q相对于三角形所有边的位置。 - 上述的采样算法需要遍历所有的像素点,其实通过观察我们可以知道,有一些像素点的遍历是无用功,其实我们呢可以根据三角形的大小获取到三角形的边界框,只遍历这个边界框内的像素点即可,如下图
- 然后我们就可以将该三角形”绘制“到屏幕上去
跟我们想要绘制的三角形还是有一定的区别的,但是形状上很相似,因此我们需要抗锯齿,反走样等技术来使绘制的结果更接近原来的形状。
至此本节课结束