Lec05 光栅化1(三角形)
文章目录
Lec05 光栅化1(三角形)投影变换(续)光栅化视口变换(Viewport Transformation)光栅化设备(补充知识)三角形光栅化采样的概念三角形采样采样速度优化存在的不足投影变换(续)
如何表示近平面的大小(l, r, b, t)和远近平面的距离(n, f)呢?事实上,用户只需设定四个参数:
垂直视锥(vertical field of view)近平面宽高比(aspect ratio = width / height)近平面距离 n远平面距离 f
(注意!上图是一张3D透视图)
由三角形关系可知,tanforvY2=tn\tan\frac{forvY}{2}=\frac{t}{n}tan2forvY=nt,aspect=rtaspect=\frac{r}{t}aspect=tr,又l=−rl=-rl=−r,b=−tb=-tb=−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)的意思。
在本课程中,为讨论方便,我们把像素简化为颜色统一的正方形,并定义屏幕空间如下:
每个像素块的下标用整数对(x, y)来表示。
视口变换(Viewport Transformation)
我们在MVP变换中得到一个[-1, 1]3的立方体,现在需要把这个立方体投射到屏幕上。这里先不考虑z坐标,只在xy平面内进行变换:把[-1, 1]2变换为[0, width] * [0, height].
从正则立方体到屏幕的变换正是视口变换。其变换矩阵如下:
Mviewport=[width200width20height20height200100001]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色块组成的:
在屏幕上光栅化的设备,除了电脑显示器,还有示波器(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.
三角形光栅化
为什么常常使用三角形作为拆解图形的单位?因为它有很多不错的性质:
三角形是最小的多边形,可以拆分其他多边形三角形在同一平面内的三角形的内外定义清晰,可以用叉乘判断内外三角形内可以定义明确的插值方法
在经过MVP变换和视口变换之后,我们可以得到一个三角形顶点的精确坐标,接下来所要做的就是用像素近似地显示出来。
我们将采用“采样”的方法来实现。
采样的概念
采样一个函数:在离散的点上对函数进行采样(求值),从而把连续的函数离散化(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);
而判断是否在三角形内,就要用到Lec02中叉乘的知识了:
若P1P2⃗×P1Q⃗\vec{P_1P_2}\times \vec{P_1Q}P1P2×P1Q,P2P0⃗×P2Q⃗\vec{P_2P_0}\times \vec{P_2Q}P2P0×P2Q,P0P1⃗×P0Q⃗\vec{P_0P_1}\times \vec{P_0Q}P0P1×P0Q 同号,则Q在三角形内。
对于边界情况(比如某个像素中心在两个三角形的公共边上),我们不必过多关注。可以自定义处理办法:比如,如果你认为边上的点算在三角形内,那么这个点就同时在这两个三角形内。
采样速度优化
为了加速采样,我们有两种简单的方法:
包围盒(Bounding Box) 递增遍历(Incremental Triangle Traverse),即对每一行,只采样三角形经过的最左像素到最右像素。该方法只适用于窄长、旋转的三角形(这种情况下包围盒不高效)
存在的不足
这样采样过后,三角形并不是平滑的,而是会出现很多锯齿。
我们将在下节课介绍反走样技术(Antialiasing)。