在光栅图形显示器上显示斜线时常会发生锯齿,这是由于直线或多边形边界在光栅图形显示器的对应图形都是由一系列相同亮度的离散象素构成的。这种用离散量表示连续亮引起的失真称为走样,而用瞎姿于减少或消除这种效果的技术,称为反走样。
一般而言,减少锯齿有三种方法,下面以直线扫描转换为例,分别介绍三种方法:
(1) 提高分辨率
假设把显示器的分辨率提高一倍,虽然直线经过2倍的象素,锯齿也会增加一倍。但由于每个锯齿在X方向和Y方向都衡神指只有低分辨率的一半,所以效果看起来会好一些,这种改进方法是以4倍的存储器代价和4倍的扫描转换时间获得的。因此增加分辨率是不经济的方法,它只能减轻,不能消除锯齿。
(2) 简单的区域取样
在直线扫描算法假定象素是数学上的一个点,象素的颜色是由对应于象素中心的图形中一点的颜色决定的。但是,实际上象素不是一个点,而是一个有限区域。屏幕上所画的直线段不是数学意义上的无宽度的理想线段,而是一个宽度至少为一个象素单位的线条。因此,把屏幕上的直线看成是长方条形更为合理。在绘制直线条时,所有与该长方条相交的象素都采用适当的宽度给予显示。这要求显示器各象素可以用多灰度显示。例,设象素中心是在网格点上的不相交的正方形,象素的灰度与它落在直线条内的面积成正比。在多灰度黑白显示器上,若一个象素整个落在线条上,则将它置成前景色。若咐配一个象素与线条部分相交,根据相交部分的大小来选择不同的灰度,相交部分大的象素前景色成分更多一些,相交部分小的象素前景色成分更少一些。这种方法将产生模糊的边界,以此来减轻锯齿效应。在实际应用中,常采用盒式滤波器
(3) 加权区域取样
加权区域取样方法采用更为优化的圆锥形滤波器。圆锥的底圆中心在当前象素中心,底圆半径为一个单位,锥高为1。当直线条经过该象素时,该象素的灰度值是在二者相交区域上对滤波器进行积分的积分值。用这种圆锥形滤波器有如下特点:一是接近理想直线的象素将被分配更多的灰度值。二是相邻两个象素的滤波器相交,所以直线条经过该相交区域时,将对这两个象素分配给适当的灰度值,这有利于缩小直线条上相邻象素的灰度差。
图形管线描述的是从图像输入到呈现在显示器上的一个流程。在这一篇里就会看到这个流程中间涉及的一些内容。中间涉及的流程可以参考下图:
光栅化按照给定的图元定点坐标,生成对应的像素,中间也会进行插值。这儿按照几个场景分别看下。
在需要画线的时候,输入是线的起始点和终点。这时候光栅化要做的是决策那些像素在这条线上。采用的方法是先表示出这条线。比如可以按照 Ax+By+C=0的形式生成该线段的表示形式:
这样在像素层面,就可以将像素坐标代入该公式看是否在该线段上。
这样是理论情况,实际上像素坐标是整数的,如果是严格按照该公式来,就可能最后算出来的线段像素点是断开的。因此就需要在线段的开始和终点之间,每行或者每列至少需要有一个像素点被认为是在该线段上。
如下所示:
简单理解下这个算法,在起点和终点之间,每次团塌增加x都需要有一个点位于该线段上,默认是水平的,如果满足某个条件,那么就更新y坐标。
那如何表示该条件呢?最直接的方法就是判断候选像素的中点和线段圆姿的关系。候选像素点是(x+1,y),(x+1,y+1),那么中点就是(x+1,y+0.5),如果该点在线段下面,说明线段更偏上一些,那么候选像素选(x+1,y+1),反之选(x+1,y)。
光栅化三角形需要区分出在三角形内的像素点和对三角形内像素点的颜色进行插值。这两个都可以通过重心坐标来完成。我们前面提到过,对于三角形内的任意一个点,都可以表示成如下形式:
这时候的算法如下:
这时候的算法如下:
在光栅化的时候还需要有一个深度的概念,就是接近观察者的物体不能被远离观察者的物体挡住。如下图所示:
图中就是两个一样大小的圆形,结果远处的圆形把近处的挡住了,这样是不合理的。针对这种情况也有一些比较直接的算法,比如画家算法,先对图形按照远近排个序,然后从远到近进行绘制,不过这种方法实际上很少用。
实际上用的最多的是z buffer算法。其实就是给每个像素增加一个深度信息。在片段混合阶段存储每个像素点的最近图元的颜色信息。这样就不依赖图元的绘制顺序了。
那这儿就涉及到深度值的表示问题,一般是用整数表示,那么就有一个精度问题,可以简单看下。如果是有B个不同的深度值,那么深度的最小变化是(f-n)/B。 按照前面介绍的透视投影z坐标换算公式:
再反一下就是投影后的z变化体现到变换前的变化:
在涉及到阴影的时候,就需要考虑是在顶点着色时处理还是片元着色时处理。定点着色会比较简单,按照顶点计算是否应橘或绝该在阴影中,然后其余交给光栅化去插值。好处是运算量小,不过效果可能不会很好,由于是按照图元顶点来的,那么小于图元的细节就处理不了了。如下图所示:
可以看到高光处有明显的三角形痕迹。
另外一个方法就是在片元处理的时候计算阴影,由顶点着色器将光源的方向和点的法线信息传过来。好处是效果好一些,不过运算量会大一些。下面是片元处理的效果图:
在前面介绍画线时我们提到来决策是否在线段上是按照像素来的,那么一个像素要不在线段上,要么不在,那么这样的像素值就会呈现出锯齿状,这就是走样。为了让效果更逼真一些就需要做反走样处理,其实就是对每个像素点做一个卷积,类似于低通滤波,其实就是在对边缘像素点计算颜色的时候,不是直接非黑即白,而是按照周围的像素点取平均。这时候的效果如下:
上面的是反走样处理后的,下面的是原始的锯齿线。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)