计算机图形学教材第二章光栅图形学希赛教育基础学院Word文档格式.docx
《计算机图形学教材第二章光栅图形学希赛教育基础学院Word文档格式.docx》由会员分享,可在线阅读,更多相关《计算机图形学教材第二章光栅图形学希赛教育基础学院Word文档格式.docx(22页珍藏版)》请在冰豆网上搜索。
该算法构思巧妙,使得每次只需检测误差项的符号就能决定直线上的下一个像素的位置。
算法原理如下:
过各个像素的中心构造一组虚拟网格线,首先按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后,采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列像素中与此交点最近的像素。
先考虑斜率k=dy/dx≤1的直线。
如图2.1所示,设直线
方程为
,其中,k=dy/dx。
假设当前像素的x坐标已经确定为xi,其y坐标为yi,由于坐标(xi,yi)(i=0,1,…)只能取整数,那么下一个像素的x坐标
,而yi+1的坐标有两种可能:
1)
保持不变,即yi+1=yi;
或者
2)
y坐标递增1,即yi+1=yi+1。
令
,y坐标是否增加1取决于如图所示误差项di的值。
因为直线的起始点在像素中心,所以初始误差d0=0。
x每增加1,y的值相应递增直线的斜率值k,即
。
一旦di+1≥1,就把它减去1,这样保证di+1在0~1之间。
当di+1≥0.5时,直线
与x=xi+1的垂线的交点最接近于当前像素(xi,yi)的右上方像素(xi+1,yi+1);
而当di+1<
0.5时,其交点更接近于(xi,yi)右边的像素(xi+1,yi)。
为方便计算,令e0=-0.5,ei+1=di+1-0.5,增量为k。
当ei+1≥0时,取当前像素(xi,yi)的右上方像素(xi+1,yi+1);
而当ei+1<
0时,更接近于右方像素(xi+1,yi)。
直线的基本要求
因此,算法2.1可以改进如下:
图2.1Bresenham画线算法
上述算法在计算直线斜率和误差时要用到浮点运算和除法,可以改用整数运算并避免使用除法,以便提高运算速度。
由于上述算法中只用到误差项的符号,因此可作一个简单变换:
。
考虑到xy平面上各种八分和四分区域的对称性,Bresenham画线算法的原理对任意斜率的直线都有其通用性。
例如,对于斜率k>
1的直线,只要在上述算法中交换x和y之间的规则即可。
算法2.1画斜率0≤k≤1的直线的改进的Bresenham画线算法:
voidBresenhamLine(intx0,inty0,intx1,inty1,longcolor)
{
intx,y,dx,dy;
floatk,e;
dx=x1-x0;
dy=y1-y0;
e=-dx;
x=x0;
y=y0;
if(dx==0)
{
for(i=0;
i≤dy;
i++)
{
DrawPixel(x,y+i,color);
//画像素(x,y+i)
}
return;
}
for(i=0;
i≤dx;
DrawPixel(x,y,color);
//画像素(x,y)
x++;
e+=e+2*dy;
if(e≥0)
{
y++;
e-=2*dx;
}
2.2
画圆
这一节中,我们介绍画圆弧的Bresenham算法。
不失一般性,假设圆的圆心位于坐标原点(如果圆心不在原点,可以通过坐标平移使其与原点重合),半径为R。
以原点为圆心的圆C有四条对称轴:
x=0,y=0,x=y和x=-y。
若已知圆弧上一点P1=C(x,y),利用其对称性便可以得到关于四条对称轴的其它7个点,即:
P2=C(x,-y),
P3=C(-x,y),
P4=C(-x,-y),
P5=C(y,x),
P6=C(-y,x),
P7=C(y,-x),
P8=C(-y,-x)。
这种性质称为八对称性。
因此,只要扫描转换八分之一圆弧,就可以通过圆弧的八对称性得到整个圆。
为了方便起见,考虑位于第一象限的四分之一圆弧。
如果以点(0,R)为起点按顺时针方向生成圆,则在第一象限内y是x的单调递减函数。
假设圆心和起点均精确地落在像素中心上。
如果已经知道圆弧上的一点(x,y),下一像素的选取有三种可能:
正右方像素,右下角像素和正下方像素,分别用H,D和V表示,如图2.2所示。
这三个像素的偏差的平方为:
令
,
如果
,说明圆弧到D向像素的距离大于到H向像素的距离,因此,下一个像素应当取H向的像素(xi+1,yi);
反之,下一个像素应当取D向的像素(xi+1,yi-1)。
经过更进一步地分析后,可以得到:
如公式(2-2-1)
如公式(2-2-2)
我们可以按以下规则选取下一个像素作为圆弧的最佳逼近点:
∙当
时,如果
,则取为下一个像素点,否则取D为下一个像素点。
∙当
,则取D为下一个像素点,否则取V为下一个像素点;
时取D为下一个像素点。
为了提高计算速度,我们可以在Bresenham画圆算法中采用只有加、减和移位(即:
乘以2)操作的递推公式如下:
可见,只用加、减和移位操作便完全可以实现Bresenham画圆算法。
和改进的Bresenham画线算法一样,Bresenham画圆算法具有很高的速度和效率,因此得到广泛的应用。
八对称性
图2.2第一象限圆弧的像素选取
2.3画椭圆
中心在原点、轴对齐的椭圆的非参数化方程为:
上式可用隐式方程表示为:
由于椭圆的对称性,仅考虑在第一象限的椭圆弧即可。
椭圆弧的法向量计算公式为:
椭圆弧上斜率为-1的点将椭圆弧分为上、下部分,见图2.3所示。
在上部分(区域2),法向量的y向分量较大,选择像素时增量Δy比较重要;
在下部分(区域1),法向量的x分量较大,选择像素时增量Δx比较重要。
下面我们分开进行讨论。
在区域2,设当前位置为
点,下一个可能的点是像素点H
和D
,这时可构造判别式:
若
<
0,表示像素点H和D的中点在椭圆内,这时可取H为下一个像素点;
若
>
=0,表示像素点H和D的中点在椭圆外,这时应当取D为下一个像素点。
所以,对于在区域2的椭圆弧,我们可以按左边的规则选取下一个像素作为椭圆弧的最佳逼近点:
图2.3第一象限椭圆弧的像素选取
2.4其它曲线
二次曲线的一般方程为
,
我们可以对二次曲线进行分类:
二次曲线也可以用参数方程表示为:
如果
时,则r(t)是一条抛物线;
当
时,r(t)是一条双曲线;
时,r(t)是椭圆。
当Δ<
0,图形为椭圆或圆弧;
当Δ=0,图形为抛物线;
当Δ>
0,图形为双曲线
对于椭圆和圆弧,我们可以用前面的方法进行光栅化显示。
对于双曲线,我们可以采用差分的方法进行光栅图形显示。
对于三次或三次以上的多项式曲线f(x,y)=0,可以采用递归空间子分算法进行光栅图形显示。
其基本思想是:
首先建立有顶点(
)和(
)构成的包围盒,如果曲线f(x,y)=0通过包围盒,而且包围盒的大小大于一个像素,则对包围盒再进行子分,直到包围盒只有一个像素大为止,然后用给定曲线的颜色输出;
如果曲线f(x,y)=0不通过包围盒,则该区域用背景色显示,并忽略处理。
2.5区域填充
1)多边形
由一系列首尾相连的直线段构成的图形称为多边形。
如果在多边形内任意选取不相同的两点,其连线上的所有点均在该多边形内,这样的多边形称为凸多边形;
否则,称为凹多边形。
2)种子填充算法
种子填充算法又称为边界填充算法。
从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。
如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止。
种子填充算法常用四连通域和八连通域技术进行填充操作。
从区域内任意一点出发,通过上、下、左、右四个方向到达区域内的任意像素。
用这种方法填充的区域就称为四连通域;
这种填充方法称为四向连通算法。
从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下八个方向到达区域内的任意像素。
用这种方法填充的区域就称为八连通域;
这种填充方法称为八向连通算法。
一般来说,八向连通算法可以填充四向连通区域,而四向连通算法有时不能填充八向连通区域。
例如,八向连通填充算法能够正确填充如图2.4a所示的区域的内部,而四向连通填充算法只能完成如图2.4b的部分填充。
图2.4四向连通填充算法
四向连通填充算法:
a)种子像素压入栈中;
b)如果栈为空,则转e);
否则转c);
c)弹出一个像素,并将该像素置成填充色;
并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;
d)转b);
e)结束。
四向连通填充方法可以用递归函数实现如下:
算法2.3四向连通递归填充算法:
voidBoundaryFill4(intx,inty,longFilledColor,longBoundaryColor)
{
longCurrentColor;
CurrentColor=GetPixelColor(x,y);
if(CurrentColor!
=BoundaryColor&
&
CurrentColor!
=FilledColor)
SetColor(FilledColor);
SetPixel(x,y);
BoundaryFill4(x+1,y,FilledColor,BoundaryColor);
BoundaryFill4(x-1,y,FilledColor,BoundaryColor);
BoundaryFill4(x,y+1,FilledColor,BoundaryColor);
BoundaryFill4(x,y-1,FilledColor,BoundaryColor);
}
上述算法的优点是非常简单,缺点是需要大量栈空间来存储相邻的点。
一个改进的方法就是:
通过沿扫描线填充水平像素段,来处理四连通或八连通相邻点,这样就仅仅只需要将每个水平像素段的起始位置压入栈,而不需要将当前位置周围尚未处理的相邻像素都压入栈,从而可以节省大量的栈空间。
3)其它填充算法
扫描线填充算法是另一个常用的多边形填充算法。
对于一个给定的多边形,用一组水平或垂直的扫描线进行扫描,分别求出每条扫描线与多边形的交点,这些交点将扫描线分割为相间排列的落在多边形内和多边形外的线段,将落在多边形内的所有线段上的每个像素点赋以给定的多边形填充色。
具体算法可以参考第7章"
消隐显示"
的相关内容。
2.6字符生成
在计算机图形学中,字符指计算机在文本方式下能够在屏幕上显示的数字、字母、音标、标点符号、数学符号、汉字等符号。
计算机中的字符由一个数字编码唯一标识。
最流行的字符集是"
美国信息交换用标准代码集"
简称ASCII码。
它用7位二进制编码规定了129个字符代码,其中代码0~31表示控制字符,32~127表示字母、标点符号、数学符号以及一些特殊符号。
我国除采用ASCII码外,还另外制定了汉字编码的国家标准字符集,如:
"
信息交换用汉字编码字符集基本集"
GB2312-80。
该字符集分为94个区,94个位,每个符号由一个区码和一个位码共同标识。
区码和位码各用一个字节表示。
为了能够区分ASCII码与汉字编码,采用字节的最高位来标识:
最高位为0表示ASCII码;
最高位为1表示汉字编码。
共收录了6763个常用汉字。
2000年3月信息产业部和国家质量技术监督局又颁布了GB18030-2000国家标准"
信息交换用汉字编码字符集基本集的扩充"
它共收录了2.7万多个汉字,总编码空间超过150万个码位,采用单/双/四字节混合编码,与现有绝大多数操作系统、中文平台在内码一级兼容,可支持现有应用系统,并包容了其中收录的所有汉字和蒙、藏、彝、维等少数民族文字。
为了在显示器等输出设备上输出字符,计算机系统中必须安装相应的字库。
字库分为点阵字库和矢量字库两种,用于存储每个字符的形状信息。
点阵字库中,每个字符用二值点阵信息表示每个字符,矢量字库则用直线和曲线(如三次B样条曲线/Bezier曲线)来描述每个字符的轮廓形状。
1)点阵字符
在点阵字库中,每个字符由一个位图表示(如图2.5所示),并把它用一个称为字符掩膜的矩阵来表示,其中的每个元素都是一位二进制数,如果该位为1表示字符的笔画经过此位,该像素置为字符颜色;
如果该位为0,表示字符的笔画不经过此位,该像素置为背景颜色。
点阵字符的显示分为两步:
首先从字库中将它的位图检索出来,然后将检索到的位图写到帧缓冲器中。
在实际应用中,同一个字符有多种字体(如宋体、楷体等),每种字体又有多种大小型号,因此字库的存储空间十分庞大。
为了减少存储空间,一般采用压缩技术。
图2.5字符的点阵表示和矢量轮廓表示
2)矢量字符
矢量字符记录字符的笔画信息而不是整个位图,具有存储空间小,美观、变换方便等优点。
例如:
在AutoCAD中使用图形实体-形(Shape)-来定义矢量字符,其中,采用了直线和圆弧作为基本的笔画来对矢量字符进行描述。
对于字符的旋转、放大、缩小等几何变换,点阵字符需要对其位图中的每个象素进行变换,而矢量字符则只需要对其几何图素进行变换就可以了,例如:
对直线笔画的两个端点进行变换,对圆弧的起点、终点、半径和圆心进行变换等等。
矢量字符的显示也分为两步。
首先从字库中将它的字符信息。
然后取出端点坐标,对其进行适当的几何变换,再根据各端点的标志显示出字符。
轮廓字形法是当今国际上最流行的一种字符表示方法,其压缩比大,且能保证字符质量。
轮廓字形法采用直线、B样条/Bezier曲线的集合来描述一个字符的轮廓线。
轮廓线构成一个或若干个封闭的平面区域。
轮廓线定义加上一些指示横宽、竖宽、基点、基线等等控制信息就构成了字符的压缩数据。
2.7光栅图形反走样基础
Bresenham直线算法生成的直线图形一般都呈阶梯状(见图2.1),实际上,这是光栅图形的一种走样现象。
这种走样现象是由于采用离散量表示连续量引起的。
通常,我们把由离散量表示连续量引起的失真称为走样;
把减少或克服走样效果的技术称为反走样技术,简称反走样。
光栅图形的走样有如下几种:
a)产生阶梯或锯齿形;
b)细节或纹理绘制失真;
c)狭小图形遗失;
d)实时动画忽隐忽现、闪烁跳跃。
当走样严重时,可能导致意外的结果。
例如,考虑图2.6a)和b)所示的信号,它们是两组完全不同的信号,对它们用同一频率进行采样(见图2.6中的黑点),重建后的信号却相同。
图2.6c)或d)是图2.6a)信号的走样,也是图2.6b)信号的走样。
造成走样的原因是由于采样频率太低造成的欠采样。
根据采样定理,为了避免走样,采样频率至少应是信号最高频率的2倍。
对于小于像素尺寸的图形对象,一方面,如果它未能覆盖像素中用于计算其属性的像素中点,则这个对象将不会显示出来;
另一方面,如果它覆盖了像素中用于计算其属性的那一点,它将不恰当地代表整个像素的属性。
图2.7就是这样的一个例子。
当在光栅设备上显示图2.7a)所示的一组细长的多边形时,由于仅仅当像素中心被这些矩形覆盖时该像素才被显示,因此造成狭小的图形遗失、图形细节失真,其结果如图2.7b)所示。
在动画序列中,这种走样现象会导致图形时隐时现,产生闪烁。
图2.8是一个小卡通动画序列中的三幅画。
如果像素的属性由其中心决定,则在第一帧中,这个小卡通人是不可见的,在第二帧小卡通人可见,但第三帧又不可见。
这样,小卡通人给人的感觉不是在缓慢地连续前进,而是一明一暗地在闪烁。
图2.6不同信号a)和b)的采样及走样现象
图2.7光栅图形的细节失真
图2.8动画的走样现象
为了提高图形质量,必须克服或减少走样现象。
这就是本节研究的重点。
光栅图形的反走样方法主要有两类:
第一类是超采样或称后置滤波。
这类算法的基本思想着眼于提高分辨率,虽然采用高分辨率的光栅图形显示器也是一个选择,但它受到客观条件的限制,而且也不经济。
因此,我们往往采用软件实现的方法,即:
将低分辨率的图形像素划分为许多子像素,在较高分辨率上对各子像素的颜色值或灰度值进行计算,然后采用某种平均算法,将原像素内的各子像素的颜色值或灰度值的平均值作为该像素显示的颜色值或灰度值,在较低分辨率的光栅图形设备上进行显示。
第二类方法称为前置滤波。
即:
把像素作为一个有限区域而不是一个面积为零的点来处理。
2.7.1直线反走样
一、反走样细直线
可以用超采样方法来进行直线反走样。
将每个像素分成n×
n个子像素,然后在子像素级对直线进行光栅化,这样就可以得到每个像素中被激活的子像素的个数。
如图2.9所示,粗实线正方形表示物理像素,虚线正方形表示子像素,阴影区域表示被激活的子像素。
在n×
n伪光栅上,可以光栅化的子像素最多为n个。
每个物理像素的光强与其被激活的子像素数与n的比值成正比。
假设一个物理像素中被激活的子像素有m个,其可能的最大光强为Imax,则该像素的光强(亮度)
(2-7-1)
再取整,即可得到象素的显示灰度值。
图2.9反走样细直线的超采样
二、区域反走样算法
a)反走样固定宽度直线的区域采样方法
假定每个象素都是一个面积等于1的小正方形矩形区域,将直线段看作宽度为一个像素的狭长矩形,如图2.10所示。
这时可以采用简单的区域采样方法进行反走样。
当直线段的矩形边界与象素的边界有交时,求出两者相交区域的面积,然后根据相交区域面积的大小确定该象素的亮度值。
对于图2.10中的任何一个阴影像素而言,上述阴影面积A是介于0-1之间的正数,用它乘以象素的最大光强为Imax,则该像素的光强
Pietteway和Winkins对Bresenham画线算法稍作改进后得到像素在多边形内的面积近似值,并用它调制像素的光强。
改进后的Bresenham反走样画线算法如下:
图2.10固定宽度直线
BresenhamAntialiasingLine(intx1,inty1,intx2,inty2,intI)
//(x1,y1),(x2,y2)分别是直线的起点和终点
//I是画线的最大亮度值
{
intx,y,dx,dy,m,w,e;
x=x1;
y=y1;
dx=x2-x1;
dy=y2-y1;
m=I*dy/dx;
w=I-m;
e=I/2;
SetPixel(x,y,m/2);
while(x<
x2)
if(e<
w)
x++;
e+=m;
else
x++;
y++;
e-=m;
SetPixel(x,y,e);
b)加权区域反走样算法
从采样理论的角度考虑,区域采样方法相当于使用盒式滤波器进行前置滤波后再采样。
区域采样方法有两个缺点:
(1)象素的亮度与相交区域的面积成正比,而与相交区域落在象素内的位置无关,这在某种程度上仍然会导致阶梯现象。
(2)直线条上沿理想直线方向的相邻两个象素有时会有较大的亮度差,特别是当直线是一条接近水平或接近垂直的直线时,这种现象就会比较突出。
为了使靠近理想直线的像素能够分配到更大的亮度值,可以采用圆锥形滤波器,如图2.11所示。
建立一个底圆半径为一个像素单位,高为1的圆锥,并使底圆中心位于当前像素中心。
当直线经过该像素时,直线的矩形区域与该圆锥底面的相交区域上对滤波器的积分,就是该像素的亮度值。
在几何上,这个积分的结果相当于用过直线矩形区域的两边沿、且垂直于像素区域的一对平面,与该圆锥相切割所得到的三维物体的体积。
这种区域采样法的反走样效果较好。
为了简化计算,我们可以采用离散的区域反走样方法。
图2.11圆锥形滤波器
三、离散区域反走样算法
a)基本原理
如图2.12所示,首先将屏幕象素均分成n×
n个子像素。
然后,对于每个物理像素,计算中心点落在直线段内的子象素的个数m,则该象素的光强为:
(2-7-2)
注意,上式与(2-7-1)式是不同的。
这里有(n2+1)种可能的光强,而反走样细直线只有(n+1)种可能的光强。
图2.12区域取样法反走样固定宽度直线
对于彩色的情况,反走样图形的光强还需要考虑背景色。
一般可取两者的线性插值。
像素的红、