概述
Scanline triangle rasterizer
将三角形分成4类:
1、平顶三角形
2、平底三角形
3、右边为主
4、左边为主
1、平顶三角形
void
2、平底三角形
void
3、后两种三角形
求解
void
Bounding Box + 判断点是否在三角形内
对三角形所在区域提取边界框
扫描边界框内的所有点
判断点是否在三角形内部
- 最简单粗暴,通过叉积判断是否在三角形内部
如果
Barycentric Algorithm
思路属于 { bounding box + 判断点是否在三角形内部 }
三角形共顶点的两边对应的向量构成平面空间的一组基底,平面上任意点可以被这组基底表示
解方程得到
时,可以判断点
所以:
需要注意
说明:算法思路简单明了,但对于每个点都要计算一次叉积,不够快捷
Edge Equation
思路属于 { bounding box + 判断点是否在三角形内部 }
直线方程
其中
- 思路概述
对于一般直线方程来说,点在直线上,代入方程为0;点在直线一侧,代入方程,恒正或恒负
如果直线上两点是已知的,那么直线两侧的正负情况与两点的顺序有关联。
比如,如果直线AB左侧的点代入直线方程,结果为正,那么直线BA应是右侧的点代入方程为正。
可想而知,当三角形根据一致的顺序(正逆时针)排列顶点并按相同的算法获得三边直线方程时:
三角形内部外部的点代入三边直线方程得到的正负符号是一致正或一致负的。
据此,可以判断点是否在三角形内部
- 根据两点获取直线方程的方法
思路:
齐次坐标下,二维坐标点扩充为三维向量,并且第三维是1.
可以认为所有所有点都落在三维空间中 z=1 平面上.
向量OA与向量OB的叉积将垂直于直线AB所在平面.
直线上的点与该叉积的内积将始终为0.
由此,可以获得该直线方程。 即,通过叉积直接获得直线方程的系数.
直线方程:
上式可以认为向量
当直线经过原点附近时,常数项
所以改用下式计算C值:
直线上的点使方程成立,直线一侧的点使方程恒正或恒负
对于两个点叉积计算系数得到的直线方程来说
另外,此处用
- 关于向量
左侧的点使方程恒正的解释
- 判断点是否在三角形内
在右手系中
当根据逆时针方向获得三边直线方程时,三角形内的点代入三直线方程,结果都是正值
顺时针时,结果都是负值
edge-equation便于线性插值
- 获得直线方程后,方便对三角形内部的点进行相关参数的线性插值
当相关参数对于点的坐标满足线性时,有如下方程成立:
此时只要求解了线性方程的系数,就可以根据点的坐标对三角形内部点的相关参数进行插值。
三个顶点的参数是已知的,所以有如下方程成立:
其中伴随矩阵刚好可以用直线方程表示,而且行列式也可以用直线方程中的系数
另外,有意思的是,三角形面积与上述行列式有如下关系:
关于该面积公式的解释:
- 该公式可以通过作图法证明,其中用到了“二维平面上的三角形面积等于两边叉积所得向量模的一半”这一性质
- 还可以通过行列式的几何意义解释该公式:
二维行列式可以认为是两个平面向量张成平行四边形的面积,三维行列式可以认为是三个空间向量张成六面体的体积。
对于空间向量
可以发现在计算行列式的过程中,顺便求解了三角形面积。 而这个面积不是普通的面积,这个面积是“有向面积”,通过行列式几何意义得到的面积或体积都是有向的。对于右手系来说,逆时针排列向量计算得到的面积、体积都是正的。 于是,根据计算得到的面积值的正负,可以判断三角形是正面还是反面。
if(逆时针为正面){
if(S>0)
正面三角形
else
反面三角形
}
- 最后,插值公式总结为:
对于边界点的处理
对于两个三角形公共边需要特殊处理一下
如果按照属于两个三角形来处理两次,当渲染透明物体时会导致 "double hitting"
如果不做处理会产生洞
通常约定,当公共边是三角形上面或左面的边时做处理,右面或下面的边则不做处理,以此来保证只处理一次
- 该规则可以通过 edge-equation 给出数学形式
对于
对于
公共边对相邻三角形分别计算的边界方程向量是正好相反的
所以同一条边对两个三角形得到的向量元素的正负属性是不同的
图中
所以从边界方程向量的几何意义上看,
// 最后,边界判定方法如下:
// 对于当前三角形,E是边界方程,(A,B,C)是边界方程对应向量
bool tie = A!=0?A>0:B<0;
if( E(x,y) >0 || (E(x,y)==0 && tie))
pixel is covered;
增量
有了edge-equation,并不需要逐个点代入方程判断是否在三角形内
而是可以通过增量的形式快速获得结果
同理
批量处理
可以对bounding box内的像素划分成block,依次判断block的四个角点,如果角点都在三角形内,则此block内部的点可以直接处理而不用再做判断。 通过划分block和增量的方法可以加速光栅化过程。
- 存在的问题
如果三角形比较纤细,划分成block效果不明显
可以求出三角形形状的大致描述:
给出经验区间
if(shape > 0.4 && shape<1.6)
edge-equation方法
else //比较纤细的三角形
scanline方法
最后
以上就是笨笨心锁为你收集整理的上面两点下面一个三角形_三角形光栅化的全部内容,希望文章能够帮你解决上面两点下面一个三角形_三角形光栅化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复