Chapter 8 The Graphics Pipeline
找到图像中每一个被几何图元占据的像素的过程叫做光栅化(rasterization)。
8.1 Rasterization
对每一个输入的图元,光栅器(rasterizer)都有两个工作,枚举图元覆盖的所有像素以及对顶点属性进行插值,光栅器的输出是一系列片元(fragment),对应一个被图元覆盖的像素。
8.1.1 Line Drawing
Line Drawing Using Implicit Line Equations
最常用来画的隐式直线方程的方法是中点算法(midpoint algroithm)。
f ( x , y ) ≡ ( y 0 − y 1 ) x + ( x 1 − x 0 ) y + x 0 y 1 − x 1 y 0 = 0 f(x,y)\equiv(y_0-y_1)x + (x_1-x_0)y+x_0y_1-x_1y_0 = 0 f(x,y)≡(y0−y1)x+(x1−x0)y+x0y1−x1y0=0
其中 x 0 ≤ x 1 x_0\le x_1 x0≤x1,那么直线的斜率为
m = y 1 − y 0 x 1 − x 0 m = \frac{y_1-y_0}{x_1-x_0} m=x1−x0y1−y0
中点算法的核心是画一条尽量细并且没有缺口的线。从左至右绘制一条上斜线,绘制一个像素只有两种可能,与左侧的像素位于相同高度位置,或者比左侧高一个像素。每一列都应该有一个像素,没有像素就会有一个缺口,两个像素就会使线变粗。
重点算法的伪代码
y = y0
for x = x0 to x1 do
draw(x,y)
if (some condition) then
y = y + 1
算法的关键是确定if条件何时生效。
一个有效的方式是利用两个候选像素的重心点与直线方程的位置关系来指定选用哪个像素
判断点与直线的位置关系 https://www.cnblogs.com/learnforever/p/9498986.html
当直线斜率位于合适的范围内时,这种方法可以有一个比较好的结果。
可以使用增量的思路改进当前的算法,算法的核心是求 f ( x + 1 , y + 0.5 ) f(x+1, y+0.5) f(x+1,y+0.5),在之前的循环中已经计算得到 f ( x − 1 , y + 0.5 ) 或 f ( x − 1 , y − 0.5 ) f(x-1,y+0.5)或f(x-1,y-0.5) f(x−1,y+0.5)或f(x−1,y−0.5),可以得到
f ( x + 1 , y ) = f ( x , y ) + ( y 0 − y 1 ) f ( x + 1 , y + 1 ) = f ( x , y ) + ( x 1 − x 0 ) + ( y 0 − y 1 ) f(x+1, y) = f(x, y) + (y_0 - y_1) \\ f(x+1, y+1) = f(x, y) +(x_1 - x_0) + (y_0 - y_1) f(x+1,y)=f(x,y)+(y0−y1)f(x+1,y+1)=f(x,y)+(x1−x0)+(y0−y1)
对应的伪代码
y=y0
d=f(x0+1,y0+0.5)
for x=x0 to x1 do
draw(x,y)
if d<0 then
y=y+1
d=d+(x1-x0)+(y0-y1)
else
d=d+(y0-y1)
8.1.2 Triangle Rasterization
当绘制三角形时,通常需要对顶点属性在三角形内进行插值,使用质心坐标(barycentric coordinates),可以很容易实现这个目的,比如说如果三个顶点的颜色分别为 c 0 , c 1 , c 2 c_0,c_1,c_2 c0,c1,c2,点的质心坐标为 ( α , β , γ ) (\alpha,\beta,\gamma) (α,β,γ),那么改点的颜色为
c = α c 0 + β c 1 + γ c 2 c = \alpha c_0+\beta c_1 +\gamma c_2 c=αc0+βc1+γc2
这种对颜色进行插值的方法称为Gouraud插值。
另一个在光栅化三角形时需要关注的问题是共享顶点和共享边的问题,需要确保相邻的两个三角形之间不存在中空的情况。如果使用中点算法来对三角形的每个边进行绘制,如果两个三角形的颜色不同,那么边的颜色将取决于绘制的顺序。