Lec05 光栅化1(三角形)
投影变换(续)
如何表示近平面的大小(l, r, b, t)和远近平面的距离(n, f)呢?事实上,用户只需设定四个参数:
- 垂直视锥(vertical field of view)
- 近平面宽高比(aspect ratio = width / height)
- 近平面距离 n
- 远平面距离 f
![](https://img-blog.csdnimg.cn/20210217113429862.jpg)
(注意!上图是一张3D透视图)
由三角形关系可知, tan f o r v Y 2 = t n \tan\frac{forvY}{2}=\frac{t}{n} tan2forvY=nt, a s p e c t = r t aspect=\frac{r}{t} aspect=tr,又 l = − r l=-r l=−r, b = − t b=-t b=−t,至此所有信息都可以通过用户输入信息转化而来。
小结:MVP变换
- Medel transformation (placing objects)
- View transformation (placing camera)
- Projection transformation
- Orthographic projection (cuboid to “canonical” cube [-1, 1]3)
- Perspective projection (frustum to “canonical” cube)
光栅化
我们已经把三位的图像投射到二维平面上了,接下来的任务就是要在屏幕上显示出来。
屏幕,其实就是像素(Pixel, short for picture element)的阵列。屏幕显示的结果与分辨率(resolution,也即像素的数量)和光栅显示方法(raster display)有关。
光栅化(rasterize),就是控制像素的显示,从而把图像“绘制”到屏幕上的过程。raster在德语中正是屏幕(screen)的意思。
在本课程中,为讨论方便,我们把像素简化为颜色统一的正方形,并定义屏幕空间如下:
![](https://img-blog.csdnimg.cn/2021021711342183.jpg)
每个像素块的下标用整数对(x, y)来表示。
视口变换(Viewport Transformation)
我们在MVP变换中得到一个[-1, 1]3的立方体,现在需要把这个立方体投射到屏幕上。这里先不考虑z坐标,只在xy平面内进行变换:把[-1, 1]2变换为[0, width] * [0, height].
从正则立方体到屏幕的变换正是视口变换。其变换矩阵如下:
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
]
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⎦⎥⎥⎤
光栅化设备(补充知识)
在实际的显示设备中,每个像素并不是一块统一的颜色,而是由RGB色块组成的:
![](https://img-blog.csdnimg.cn/20210217113413102.jpg)
在屏幕上光栅化的设备,除了电脑显示器,还有示波器(Osciliosope)、阴极射线管(Cathode Ray Tube)、电视(CRT原理,可以每次只画奇数行/偶数行)、帧缓冲设备(调用内存里存储的图像)、液晶显示屏(LCD,Liquid Crystal Display,通过液晶的排布影响光的偏振方向,从而控制光能否通过光栅)、发光二极管(LED,Light Emitting Diode)、电子墨水屏(Eletrophoretic Display,如Kindle),etc.
除此以外,也并不一定是绘制到屏幕上。如:数控精雕机(CNC Sharpie Drawing Machine)、激光切割机(Laser Cutting Machine),etc.
三角形光栅化
![](https://img-blog.csdnimg.cn/20210217113405760.jpg)
为什么常常使用三角形作为拆解图形的单位?因为它有很多不错的性质:
- 三角形是最小的多边形,可以拆分其他多边形
- 三角形在同一平面内的
- 三角形的内外定义清晰,可以用叉乘判断内外
- 三角形内可以定义明确的插值方法
在经过MVP变换和视口变换之后,我们可以得到一个三角形顶点的精确坐标,接下来所要做的就是用像素近似地显示出来。
![](https://img-blog.csdnimg.cn/20210217113353499.jpg)
我们将采用“采样”的方法来实现。
采样的概念
采样一个函数:在离散的点上对函数进行采样(求值),从而把连续的函数离散化(discretize)。
图形学中采样也有广泛的应用:时间(1D)、区域(2D)、体积(3D),etc.
再举个例子:在人体内任何一个位置得到其密度,也是一种三维的采样。
三角形采样
类似地,对三角形的采样可以作如下解释:
给定一个三角形,对每个像素判断其中心是否在三角形内。
for (x=0; x<xmax; ++x)
for (y=0; y<ymax; ++y)
image[x][y] = inside(tri, x+0.5, y+0.5);
![](https://img-blog.csdnimg.cn/20210217113341517.jpg)
而判断是否在三角形内,就要用到Lec02中叉乘的知识了:
![](https://img-blog.csdnimg.cn/20210217113335297.jpg)
若 P 1 P 2 ⃗ × P 1 Q ⃗ \vec{P_1P_2}\times \vec{P_1Q} P1P2×P1Q, P 2 P 0 ⃗ × P 2 Q ⃗ \vec{P_2P_0}\times \vec{P_2Q} P2P0×P2Q, P 0 P 1 ⃗ × P 0 Q ⃗ \vec{P_0P_1}\times \vec{P_0Q} P0P1×P0Q 同号,则Q在三角形内。
对于边界情况(比如某个像素中心在两个三角形的公共边上),我们不必过多关注。可以自定义处理办法:比如,如果你认为边上的点算在三角形内,那么这个点就同时在这两个三角形内。
采样速度优化
为了加速采样,我们有两种简单的方法:
- 包围盒(Bounding Box)
![](https://img-blog.csdnimg.cn/20210217113328281.jpg)
- 递增遍历(Incremental Triangle Traverse),即对每一行,只采样三角形经过的最左像素到最右像素。该方法只适用于窄长、旋转的三角形(这种情况下包围盒不高效)
![](https://img-blog.csdnimg.cn/20210217113321228.jpg)
存在的不足
这样采样过后,三角形并不是平滑的,而是会出现很多锯齿。
![](https://img-blog.csdnimg.cn/20210217113301397.jpg)
我们将在下节课介绍反走样技术(Antialiasing)。