- DDA(Digital Differential Analyzer, 数值微分法) - 
 
计算机图形学中,经常会遇到一些计算机中”经典“的问题。例如,如何利用计算机”离散“的特质,模拟现实中”连续“的概念?关于这个问题的一个具体应用,就是如何利用计算机”画直线“的问题。我们知道在纯粹抽象的数学中,一条直线用y=mx+b就可以表达(其中m是斜率);但如果要画在计算机屏幕上,就没那么容易:因为计算机屏幕是由许多分散的像素格子组成的,你需要决定在什么时候换行或者换列。这种模拟的本质,还是”插值“问题。直线是最简单的情况,往复杂点说,就会有考虑如何插值三角形甚至多边形的情况。不过它们都是”直线“插值的复杂应用,下面就不多说了。
 
DDA是一种处理此种问题的经典算法。算法思想倒也不难:
 
【准备阶段】
 
1) 给定一条线段的起点(x1, y1)和终点(x2, y2),分别计算在两轴上的差值 △y = y2 - y1 和 △x = x1 - x2。
 
2) 比较△y和△x二者谁比较大,大的那一个就作为遍历的总步数。steps = max(△x, △y)。
 
3) 分别计算在x和y方向上单步的步距。 dx = △x/steps,dy = △y/steps。注意此时dx和dy必然一个等于1,一个介于0-1之间(浮点数)

【遍历阶段】

4)△x和△y谁大,谁就作为插值的主序方向。意味着每次插值都是朝这个方向行进一步。比如△x大,那么假设当前在格子(xi, yi)处,决定下一个格子时,由于在x方向是主序方向,所以朝x方向行进一步得到xi+1。剩下的就是决定y方向上到底是yi呢还是yi+1呢。

5)到底是yi还是yi+1,要看根据y = m(xi+1) + b计算出真实的y等于多少。这时的y计算出来的是浮点数,根据float2Int的一些规则,转换成对应的整形然后找到对应的格子。float2Int的转换规则要看具体情况,四舍五入还是直接截取,看效果吧。

6)重复4)-5)步

DDA算法直接了当,简单易懂。不过它的计算过程中涉及到许多浮点数运算,这在当今的CPU设计架构中运算成本较大,也可视为其运算复杂度较高。下面的Bresenham line's algorithm就是对其的一种改进。

- Bresenham line's algorithm - 

Bresenham line's algorithm 是DDA的一种改进算法。它与DDA相比有质量和效率的两点改进:

1)质量方面的改进。 比如还是以△x为主序方向行进时,决定下一个点是落在yi还是yi+1,不仅仅考虑真实计算出来的y等于多少,还要考虑这个y值是离yi更近还是离yi+1更近。谁近就画在谁的格子里。这一点显然比DDA中思考问题的方式更加make sense。

2)效率方面的改进。根据上一点的判断准则,再加上一系列的递归推导,最后简化到只存在整形的加减运算以及比较操作。这在当今CPU的架构中运算成本相对来说非常便宜,因此效率更高。具体的推导细节,参见这篇 DERIVATION OF THE BRESENHAM’S LINE ALGORITHM

- Voxel Traversal used in the Grid-Accelerator in PBRT -

我正在看pbrt的第4章。这章主要讲了有关场景管理组织的一些技术,目的是为了提高射线相交测试(ray intersection tests)的效率。主要的手段有三种,Grid-BasedBVH 和 KD-Tree。目前正看到第一种,Grid-Based,基于网格的场景管理技术 

基于网格的场景管理方法,相当于把整个场景看作是一个大的bouding box,然后对这个box所在的空间分别在三个维度上划分成一格一格的。然后将场景中的primitives与各个发生overlap的格子”关联“起来。接着,从射线的方位出发,遍历(traverse)这个网格系统,对于与射线发生相交的格子,再在里面遍历与之关联的所有primitives,对遍历到的每个primitive都做一次相交测试。当然这当中的细节还有很多,就不赘述了。总之这种算法的思想可以描述为”分而治之“。通过每个格子的空间管理与之有关的primitives,测试某个格子的时候就不必考虑其他格子里的primitives,从而可以有效降解其遍历场景的复杂度。

这里,我想强调下射线是如何遍历这个网格系统的。其方法也是DDA算法的一种改进,书中说非常像Bresenham line's algorithm。但我仔细观察了一下,和Bresenham的算法还是不一样的。这里的关键是利用的是射线的参数(parametric)方程,那个参数t(作为沿着射线方向偏离起点的距离)是很重要的。当决定下一点究竟是朝x方向,y方向还是z方向步进时,要看这条射线”最先打到哪个方向的下一格子的边界“。哪个方向的边界先被打到,就朝哪个方向步进一次。这样一来,这种算法就不是依靠决定”哪个方向是主序“的思路进行的了,每次判断步进时三个方向皆有可能步进。这点与经典的DDA(包括Bresenham)算法都非常不同。

我知道我没说清楚,刚才在网上粗略找了找,发现这篇应该才是pbrt中使用的算法:A Fast Voxel Traversal Algorithm for Ray Tracing。(我没细看,大体觉得差不了)。欢迎指正校对勘误拍砖头,谢谢。

DDA, Bresenham line's algorithm and Voxel Traversal used in the Grid-Accelerator in PBRT的更多相关文章

  1. 计算机图形学之扫描转换直线-DDA,Bresenham,中点画线算法

    1.DDA算法 DDA(Digital Differential Analyer):数字微分法 DDA算法思想:增量思想 公式推导: 效率:采用了浮点加法和浮点显示是需要取整 代码: void lin ...

  2. 【A Global Line Matching Algorithm for 2D Laser Scan Matching in Regular Environment】

    只看了前面的部分,灭有看实验,觉得整体风格比较傻白甜,与我的想法不谋而合.简单明了,用起来应该比较方便. 初步探测:如果有直线,就给线性插值一下. 分级聚类:利用简单的阈值给聚类了一下,分成了段段. ...

  3. C# Cut Line Bressenham Algorithm

    using System; using System.Drawing; using System.Windows.Forms; namespace CutLine { static class Pro ...

  4. 【十天自制软渲染器】DAY 02:画一条直线(DDA 算法 & Bresenham’s 算法)

    推荐关注公众号「卤蛋实验室」或访问博客原文,更新更及时,阅读体验更佳 第一天我们搭建了 C++ 的运行环境并画了一个点,根据 点 → 线 → 面 的顺序,今天我们讲讲如何画一条直线. 本文主要讲解直线 ...

  5. Bresenham直线算法与画圆算法

    在我们内部开发使用的一个工具中,我们需要几乎从 0 开始实现一个高效的二维图像渲染引擎.比较幸运的是,我们只需要画直线.圆以及矩形,其中比较复杂的是画直线和圆.画直线和圆已经有非常多的成熟的算法了,我 ...

  6. Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法

    Gradient Descent 机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一.梯度下降(Gradient Descent)[3]也被称之为最快梯度(St ...

  7. Line Search and Quasi-Newton Methods

    Gradient Descent 机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一.梯度下降(Gradient Descent)[3]也被称之为最快梯度(St ...

  8. 中点Bresenham画圆

    这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步. 算法步骤: (1) 输入圆的半径R. (2) 计算初始值d = 1 - ...

  9. 改进的Bresenham算法

    这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步. 算法步骤: (1) 输入直线的两端点P0 (x0, y0)和P1 (x ...

随机推荐

  1. MySQL查询练习(45道)

    题目:设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher). 四个表的结构分别如表1-1的表(一)~表(四)所示,数据如表1 ...

  2. All Start Here.

    缘由 本博客是为天大软院 2016 级研一课程"现代软件工程"的课程设计而开设.同时借此机会和同学们进行技术交流与分享. 我们小组共有四位成员: 陈岩岩 2016218020 刘莞 ...

  3. verilog选择数据类型时常犯的错误

    •    信号可以分为端口信号和内部信号.出现在端口列表中的信号是端口信号,其它的信号为内部信号. •    对于端口信号,输入端口只能是net类型.输出端口可以是net类型,也可以是register ...

  4. shell 命令 rz sz

    尝试了几个版本,下面的是可用的 https://segmentfault.com/a/1190000012166969

  5. 异步多线程 ASP.NET 同步调用异步 使用Result产生死锁

    一个方法调用了async方法,要将这个方法本身设计为async. public class BlogController : Controller { public async Task<Act ...

  6. 前端开发 - JavaScript 词法分析

    JavaScript代码运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 1.分析函数的参数 2.分析函数的变量声明 3.分析函数的函数声明表达式 具体步骤如下: 函数在运行的瞬间,生成 ...

  7. unigui发展路线图

    unigui发展路线图 易博龙收购了SENCHA EXT JS和UNIGUI,随之官方发布了UNIGUI的发展路线图. UNIGUI是开发WEB桌面和手机移动应用的利器. UNIGUI将支持以下新特性 ...

  8. [leetcode 120]triangle 空间O(n)算法

    1 题目 Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjac ...

  9. LogisticRegression in MLLib

    例子 iris数据训练Logistic模型.特征petal width和petal height,分类目标有三类. import org.apache.spark.mllib.classificati ...

  10. 通过 NewLife.XCode 迁移任意现有数据库到任意数据库

    通过 NewLife.XCode 迁移任意现有数据库到任意数据库(附分表分库方法) 本文背景是将其他系统的数据库迁移到另一个数据库(仅需 20 行代码),也可以作为项目迁移用,生成自己系统的专属实体代 ...