最近在学习软渲染引擎,涉及到直线的光栅化,学习了几种方法,以下是常用的两种说法。中点画线算法代码比较简洁,但由于使用了递归,效率比较低,而且画线效果也比较差;Bresenham算法则可以高效画线,并且光栅化后的直线效果要比中点画线算法的效果好很多。
1.中点画线算法
public void DrawLine(Vector2 point0, Vector2 point1)
{
var dist = (point1 - point0).Length();
if (dist < 2)
{
return;
}
Vector2 middlePoint = point0 + (point1 - point0)/2.0f;
DrawPoint(middlePoint);
DrawLine(point0, middlePoint);
DrawLine(middlePoint, point1);
}
2.Bresenham算法
//绘制坐标系:左上角为坐标原点(0, 0),向右为X轴正方向,向下为Y轴正方向
public void DrawBLine(Vector2 point0, Vector2 point1)
{
int x0 = (int) point0.X;
int y0 = (int) point0.Y;
int x1 = (int) point1.X;
int y1 = (int) point1.Y;
var dx = Math.Abs(x1 - x0);
var dy = Math.Abs(y1 - y0);
var sx = (x0 < x1) ? 1 : -1; //Step
var sy = (y0 < y1) ? 1 : -1;
var err = dx - dy;
while (true)
{
DrawPoint(new Vector2(x0, y0));
if ((x0 == x1) && (y0 == y1))
{
break;
}
var err2 = 2*err;
//2dx - dy > 0 --> dx + dx - dy > 0 --> dx > dy - dx
//因为dx >= 0, 所以 0 > dy - dx --> 1 > dy/dx
//即斜率k小于1,x方向递增步长,X = X + Step
if (err2 + dy > 0)
{
x0 += sx;
err -= dy;
}
//dx - 2dy < 0 --> dx - dy - dy < 0 --> dx - dy < dy
//因为dy >= 0, 所以 dx - dy < 0 --> 1 < dy/dx
//即斜率k大于1,y方向递增步长,Y = Y + Step
if (err2 - dx < 0)
{
y0 += sy;
err += dx;
}
}
}