渲染管线——光栅化之Bresenham绘线算法

在完成了渲染管线的几何阶段之后,我们得到了三维物体在屏幕上的二维坐标,接下来,我们将进行光栅化操作。

光栅化

计算机屏幕是由点阵构成的,这些点阵称为像素。显然,这些像素是离散的,我们是不可能精确的绘制出绝对意义平滑的直线。

这里写图片描述

所谓的光栅化,就是将图形填充到像素格上。
这里又分为线框模式的填充和实心填充。
所谓线框模式的填充,就是只描绘出三维物体的外边框。
实心的填充,即根据结点的各种几何信息,填充在像素格子上。

线框填充模式:只勾勒出了图形的外框

这里写图片描述

实体填充模式:图形内部也被填充上颜色

这里写图片描述

本文暂时只介绍线框填充模式。
很显然,线框填充的关键点在于如何根据两点在屏幕上画一条直线,这里介绍一种高效的绘线算法,
Bresenham绘线算法。(布雷森汉姆)

Bresenham绘线算法

原理

Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在n维位图上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。

为了描述算法的原理,我们做出如下假设,之后再推广到所有的情况:

(1)以常见的屏幕坐标系建立坐标系,左上角为(0,0)点,x向右方向增长,y向下增长
(2)直线的方程为y = mx + n, 且直线与x轴的夹角小于45度大于0度,也就是 0 < m < 1

如图所示:
这里写图片描述

根据直线的定义,每当x+1,y增加m。虽然x,y都是整数,但m = dy/dx未必为整数,因此y+m可能不是整数,是存在误差的,要进行该算法,我们要设定一个误差值。

这里写图片描述

误差定义为某点x实际的y与绘制的y之间的差值,例如在上图中:

x+1直线上实际对应的点是红绿线的交点(x+1,y+m+error),但是我们绘制的时候绘制的是(x+1,y+1).由图可知,每当x+1,error相应增加m,如果说error + m > 0.5,那么说明将要绘制的点距离y+1更近一点,否则距离y更近。

这个过程可以被以下代码描述:

BresenhameDrawLine(point p1, point p2){
    //p1 左上  p2 右下
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    float error = 0f;
    float m = dy/dx;
    int y = p1.y;

    for(x = p1.x ; x < p2.x; x++){
        error += m;
        if(abs(error) > 0.5){
            plot(x,y+1);
            error -= 1.0f;//为何-1.0f是因为m永远小于1
        }
        else{
            plot(x,y);
        }
        y += 1;
    }
}

一般化

虽然以上的算法只能绘画由左上至右下,且斜率小于或等于1的直线,但我们可以扩展此算法,使之可绘画任何的直线。

第一个扩展是绘画反方向,即由右下至左上的直线。这可以简单地通过在x1 > x2时交换起点和终点来做到。第二个扩展是绘画斜率为负的直线。可以检查y0 ≥ y1是否成立;若该不等式成立,误差超出0.5时y的值改为加-1。
第三个扩展是绘画斜率绝对值大于1的直线。要做到这点,我们可以利用大斜率直线对直线y=x的反射是一条小斜率直线的事实,在整个计算过程中交换 x 和 y,并一并将plot的参数顺序交换。扩展后的伪代码如下:

BresenhameDrawLine(point p1, point p2){
    bool steep = abs(p2.y
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值