反走样算法有很多种.先就<<Introduction to Computer Graphics>>中的Unweighted Area Sampling(不加权采样)和Weighted Area Sampling(加权采样)做一下讨论:
The primitives drawn using the algorithms studied before have a common problem. They have jagged edges. This undesirable effect, known as the jaggies, or staircasing, is the result of an all-or-nothing approach to scan conversion in which each pixel either is replaced with the primitive's color or is left unchanged. Jaggies are an instance of a phenomenon known as aliasing. The application of techniques that reduce or eliminate aliasing is referred to as antialiasing .
Unweighted Area Sampling
The first approach to improving picture quality can be developed by recognizing that although an ideal primitive such as the line has zero width, the primitive that is being drawn has nonzero width as shown below:
![](https://i-blog.csdnimg.cn/blog_migrate/00ccd39017f2083e5908cbafc625de6b.jpeg)
The technique of setting intensity proportional to the amount of area covered is called unweighted area sampling.
![](https://p-blog.csdn.net/images/p_blog_csdn_net/c0ffee1982/40.gif)
In weighted area sampling, we keep unweighted area sampling's first and second properties (intensity decreases with decreased area overlap, and primitives contribute only if they overlap the area represented by the pixel), but we alter the third property. We let equal areas contribute unequally: A small area closer to the pixel center has greater influence than does one at a greater distance.
To retain the second property, we must make the following change in the geometry of the pixel. In unweighted area sampling, if the edge of a primitive is quite close to the boundary of the square tile we have used to represent a pixel until now, but does not actually intersect this boundary, it will not contribute to the pixel's intensity. In the new approach, the pixel represents a circular area larger than the square tile; the primitive will intersect this larger area; hence, it will contribute to the intensity of the pixel.
对于Unweighted Area Sampling实现的算法如下,但应该注意的是在取直线经过点所占面积时应是通过计算周围一定范围内点的面积确定的(如一个正方形),确定好一个点的灰度然后继续下去直到绘完整条线.附代码如下 :
//判断某个点是否在直线矩形区域内
bool CGraphicsView:: Check(int x0,int y0, float k ,float d, float x, float y)
{
//float dy = y1 - y0,dx = x1 - x0;
//float d = 0.5 * sqrt(dx*dx + dy*dy)/dx;//在坐标x固定时直线的宽度
float yp = (x - x0)*k + y0;
if( y < yp + d && y > yp - d)
return true;
return false;
}
//取得某一个点的灰度
float CGraphicsView::GetColorDepth(int x0,int y0,float k ,float p, int x, int y)
{
float d = 0.01f;
float length = 1/d - 2;
int num = 0;
for (int i = 1;i < length;i++)
{
for (int j = 1;j < length;j++)
{
if(Check(x0,y0,k, p, x + d*i, y + d*j))
num++;
}
}//取得直线过一个正方形的像素点集的个数(面积)
float rate = num/(length * length);//由此我们确定出像素面积
return rate;
}
void CGraphicsView::AntiAliasLine (int x0, int y0, int x1, int y1)
{
float dy = y1 - y0,dx = x1 - x0;
float d = 0.5 * sqrt(dx*dx + dy*dy)/dx;//在坐标x固定时直线的宽度
float k=dy/dx;
// float yp = (x - x0)*dy/dx + y0;
for (int x = x0;x <= x1;x++)
{
for(int y = y0;y <= y1;y++)
{
//计算点的灰度值
float colorDepth = GetColorDepth( x0, y0,k,d,x,y);
glBegin(GL_POINTS); //画一个点
glColor3f(colorDepth ,colorDepth ,colorDepth );
glVertex2d(x,y);
glEnd();
}
}
}