直线的反走样算法比较简单,不做详细介绍. 需要说明的是这个算法原理我不是原创,经典书籍上都有记载,其中反走样算法都是斜率在0-1之间的直线的算法,我还真没见过完整的.所以我这里把它补充完整了,算法效率毋庸置疑,几乎不可能再快了. 第一个函数是画线的经典函数,第二个是反走样直线的算法.
和画直线算法相比较,增加的部分用 ///+ 标明了.
#define WCG_FILTER(d) ((d)>1.4142136?0:((d)<-1.4142136?0:(1-(ABS(d)*0.70711)))) inline void cg_line(int x1,int y1,int x2,int y2,int crColor) { int d, x, y, ax, ay, sx, sy, dx, dy; dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); x = x1; y = y1; if (ax>ay) { /* x dominant */ d = ay-(ax>>1); for (;;) { putpixel (x, y,crColor); if (x==x2) return; if (d>=0) { y += sy; d -= ax; } x += sx; d += ay; } } else { /* y dominant */ d = ax-(ay>>1); for (;;) { putpixel (x, y, crColor); if (y==y2) return; if (d>=0) { x += sx; d -= ay; } y += sy; d += ax; } } } inline void cg_antialiased_line(int x1,int y1,int x2,int y2,int crColor) { int d, x, y, ax, ay, sx, sy, dx, dy, fx, fy, bk; dx = x2-x1; fx=ABS(dx); ax = fx<<1; sx = SGN(dx); dy = y2-y1; fy=ABS(dy); ay = fy<<1; sy = SGN(dy); x = x1; y = y1; //// + int incrE,incrNE; double invDenom=1.0/(2.0*sqrt(1.0*dx*dx+dy*dy)); double temp=0; double temp2=0; //// + if (ax>ay) { /* x dominant */ d = ay-fx; /// + int two_v_dx=0; incrE=(dy<<1); incrNE=((dy-dx)<<2); double two_dx_invDenom=2.0*dx*invDenom; /// + for (;;) { /// + temp=two_v_dx*invDenom; temp2=sx>0?temp:-temp; bk=getpixel(x,y);putpixel(x,y,LERP_COLOR(crColor,bk,WCG_FILTER(temp))); bk=getpixel(x,y+sy);putpixel(x,y+sy,LERP_COLOR(crColor,bk,WCG_FILTER(two_dx_invDenom-temp2))); bk=getpixel(x,y-sy);putpixel(x,y-sy,LERP_COLOR(crColor,bk,WCG_FILTER(two_dx_invDenom+temp2))); /// + if (x==x2) return; if (d>=0) { two_v_dx=d-fx; /// + y += sy; d -= ax; } else two_v_dx=d+fx; /// + x += sx; d += ay; } } else { /* y dominant */ d = ax-fy; /// + int two_v_dy=0; incrE=(dx<<1); incrNE=((dx-dy)<<1); double two_dy_invDenom=2.0*dy*invDenom; /// + for (;;) { /// + temp=two_v_dy*invDenom; temp2=sy>0?temp:-temp; bk=getpixel(x,y);putpixel(x,y,LERP_COLOR(crColor,bk,WCG_FILTER(temp))); bk=getpixel(x+sx,y);putpixel(x+sx,y,LERP_COLOR(crColor,bk,WCG_FILTER(two_dy_invDenom-temp2))); bk=getpixel(x-sx,y);putpixel(x-sx,y,LERP_COLOR(crColor,bk,WCG_FILTER(two_dy_invDenom+temp2))); /// + if (y==y2) return; if (d>=0) { two_v_dy=d-fy; /// + x += sx; d -= ay; } else two_v_dy=d+fy; /// + y += sy; d += ax; } } }