光栅化学习笔记(一)

来源:互联网 发布:手机qq透明皮肤软件 编辑:程序博客网 时间:2024/04/28 18:42

此次笔记为scatchpixel网站的学习笔记,是按照原文的脉络整理的,因为并不是一字一句翻译的,所以没有设置成译文标签,而是将自己理解的还原一下,希望能用更接地气的方式把道理讲明白,如果有错误的地方希望指出。

光栅化之前由投影变换将一个将3d图元转换成2d图像,转换后的图像上的每个点都有一个颜色属性和一个深度属性。光栅化可以分为两个部分,第一个部分就是确定2d图像覆盖了窗口坐标系下哪些像素,第二部分就是确定每个像素的颜色和深度。


1变换顶点到光栅坐标空间

这里先复习下投影变换,具体推导可以看这篇。


p点为摄像机空间内一点,np为投影平面,N为近平面距离,F为远平面距离,p’为p点投影点。


假设P坐标为(cameraX,cameraY,cameraZ),

根据相似三角形很容易得到p’屏幕坐标

screenX=N*cameraX/cameraZ

screenY=N*cameraY/cameraZ

screenZ=-cameraZ

这里screenZ简单即为-z,表示原顶点的深度(cameraZ为负值,深度值取正值,所以取反) 。

然后将screenX,screenY’转换到NDC空间,

ndcX=2 * pScreen.x / (r - l) - (r + l) / (r - l); 

ndcY=2 * pScreen.y / (t - b) - (t + b) / (t - b); 


如果要判断2d图像覆盖了哪些像素,则应该将2d图像转换到像素所在的坐标系,即光栅坐标系,x范围是[0,width],y范围是[0,height],width,height为帧缓冲的宽高,由于存在图像重叠的情况,会有多个点对应同一个像素,所以需要保存原顶点的深度值,也就是-cameraZ。

所以得到

rasterX=(ndcX+1)/2 * width

rasterY=(ndcY+1)/2 * height

rasterZ=-cameraZ

2判断像素覆盖三角形


在光栅坐标空间,每个像素可以看成是一个整数坐标的点,要判断三角形覆盖了哪些像素,可以反向判断哪些像素在三角形内部即可。要判断一个点是否在三角形内部,用到了一个叫做边缘函数(edge function)的算法。


一条边将一个平面分割成左右两部分,边缘函数可以让我们根据计算结果判断一个点所处的位置:

如果结果为负值,则点在直线左边,

如果结果为正值,则点在直线右边,

如果结果为零,则点在直线上。(这里注意直线是有方向的)

下面给出边缘函数 

E01(P)=(P.x−v0.x)∗(V1.y−V0.y)−(P.y−V0.y)∗(V1.x−V0.x) (从v0到v1点向量)


有了这个算法,我们只需对三角形的三条边都进行测试,如果结果都为正(三角形顺时针卷绕),则说明点在三角形内部。

上面给出的公式,仔细观察可以看出其实是求向量v0v1与向量v0p的叉积的z坐标,所以就不用刻意去背这个公式了,只要分别求v0v1与v0p,v1v2与v1p,v2v0与v2p的叉积的坐标即可。

ok,到此给出了像素覆盖三角形的最最最基本的判断方法。

3.计算每个覆盖三角形的像素的颜色



首先感性的来看,P点的颜色应该与三个顶点的颜色是线性相关的,它对于每个顶点的颜色在混合时有一个权重,所以只要求得这三个权重,就可以求出P点的颜色。

这里引入一个概念,质心坐标系,它可以用来定义三角形平面任意点的行为有:

P=λ0∗V0+λ1∗V1+λ2∗V2,

这里我们只需要关心三角形内部的顶点,对于三角形内部的顶点有

λ0+λ1+λ2=1, for P∈△V0,V1,V2.

所以对于颜色就有了:

CP=λ0∗CV0+λ1∗CV1+λ2∗CV2

对于边上的点,如点在v0v1上,则v2点的系数λ2=0,

CP=λ0∗CV0+λ1∗CV1, λ0+λ1=1,

对于三角形的顶点,如v0,有λ1=0,λ2=0 :

CP=λ0∗CV0,λ0=1。

然后给出λ0,λ1,λ2点求法--面积法。


这里只给结论,数学证明跳过。


v0点的权重λ0为与v0相对的三角形(红色)面积占总面的比例相等,λ1,λ2同理。所以只要求由p点划分的三个三角形的面积比例就可以得到三个权重值。三角形面积可以用叉积很容易求得。

λ0=Area(V1,V2,P) / Area(V0,V1,V2),

λ1=Area(V2,V0,P) / Area(V0,V1,V2),

λ2=Area(V0,V1,P) / Area(V0,V1,V2).

同理可以对光栅坐标中的深度值进行插值,求P点的深度值。后面会详细介绍。


光栅化的原则—Top-Left-Rule

当使用边缘函数对于像素点进行判断时,如果结果为0,则表示该像素点在三角形的边上,那么如果这条边是两个三角形的公用边,那么这个条边上的像素会被计算两次,产生右边图的效果。解决方案就是Top-Left-Rule:如果像素点在三角形的边上时,只有这条边是Top边或者Left边,才算做是在三角形内。



解释:以三角形顺时针卷绕为例:

Top边:两个端点y坐标相等,x方向由左向右

Left边:两个端点y坐标不能,x方向任意


第一篇告一段落,抛砖引玉一下,关于深度,法线,纹理坐标的计算,会在第二篇继续整理,欢迎关注。




0 0
原创粉丝点击