光线投射与光线跟踪算法归纳

2021年9月12日 26点热度 0条评论 来源: edgelee

目录

  1. 前言
  2. 三维可视化与体绘制
  3. Ray Tracing vs. Ray Casting
  4. 体绘制的加速技术
  5. 基于CUDA实现Ray-Casting
  6. 后话
  7. 参考文献

 

1.       前言

在读了大牛们的很多深入浅出的科普文章和教程系列并受益匪浅后,不免有自己尝试写写的冲动。本文将尽量平白地阐述一些基本概念和算法流程,同时尽可能多地给出进一步学习所需要的有用资料,一些关键链接就省去了,感兴趣者可以google之。

向乐于分享的大牛们致敬!

 

2.       三维可视化与体绘制

大家应该对可视化(visualization)这个词并不陌生了。这里限于3D数据场的可视化。譬如,一组CT\MRI切片是人体某个部位(也不限于人体,如客运站的行李安全检查也是CT扫描)的剖面图,逐张切片图像的2D观察不够形象,医学可视化技术就是实现了3D观察­。当然也可以漫游这个3D数据场,只要变换观察点和观察角度就可以了。

图1 医学可视化

图2 流体力学模拟

也就是说,我们对现实世界进行采样而得到的一组数据,标识了这个3D空间里的采样点的某些属性;现在,把这个3D模型放在舞台上,用一台虚拟摄像机对它拍照,照片就是我们所需的可视化结果。这里的3D模型,是体模型、体数据,而传统图形学的是网格模型——我们看到的游戏人物,其实就是在建立好的3D网格模型上贴上纹理加入光照,是为“空壳”也!

3D模型不一样,那么渲染技术也不一样吗?两者的确差异很大。现在暂且不说,先讲讲其他几个概念。

3D数据场的可视化技术,可以分为面绘制(surface rendering)和体绘制(volume rendering)。

面绘制,是先抽取出3D数据场里的某个等值面,这个等值面的表示形式,是一个元素为三角面片的数组。这样,接下来用OpenGL/D3D的API函数就可以画出结果了。面绘制常用的方法有MC、MT和dividing cubes等。所以,可以说,面绘制是从原始的3D模型中抽取出我们感兴趣的某个网格模型,而忽略了其他数据。

体绘制,或者叫直接体绘制(DVR, Direct Volume Rendering),就是直接对原始的3D模型进行处理,利用了整个数据场信息。体绘制结果,不单单可以看到表面,还可以透过表面(赋予一定的透明度)看到里面。体绘制的自由度大得多,绘制结果也丰富得多,但是需要处理海量的体数据,不能直接使用图形学API,速度慢得多。其算法族有光线投射法(ray casting)、溅射法(splatting)、错切—变形法(shear-warp)、体元投射法(cell projection)和基于纹理映射(texture mapping)的方法。这样说,对于外行来说,可能还不够清楚,且看下文吧。

有书名为“Real-Time Volume Graphics”,可译为“实时体图形学”。这本书非常经典!记得年初我通过馆际互借从上海图书馆借来捧在手上时,如获至宝!——寻书的过程,也使得我对“诺大一个中国,却无书可读”深有感触。我忘记了“体图形学”是自己的译法还是在哪里见过,我们姑且用这个名称吧。看书中第一章开头:

“This book covers two seemingly very different applications of volume graphics: on the one hand, ‘special effects’ and realistic rendering of clouds, smoke, fire, and similar effects for computer games, movie production, and so forth; on the other hand, the scientific visualization of volumetric data.”

“…both fields rely on the same underlying physical models and therefore use identical, or at least very similar, rendering techniques.”

“Therefore, volume graphics targets the same goal as computer graphics in general: the simulation of light propagation in order to produce images as recorded by a virtual camera.”

到这里,你大概知道“3D模型不一样,那么渲染技术也不一样吗?”的答案了吧。如果还有疑问,又不想花太多时间,可以到“Real-Time Volume Graphics”这本书的主页上下载chapter 2的PPT看看。

 

3.       Ray Tracing vs. Ray Casting

说到“ray tracing”,先回顾一下我的计算机图形学(CG)学习过程。

开始时,因由做MC算法,把徐波译的《OpenGL超级宝典》翻了一遍,之后也看过OpenGL红宝书——感觉翻译水平有限,还不如看原版,另外推荐NeHe的OpenGL教程——其实学习CG就要做好足够的心理准备要看大量的外文资料。

之后做体绘制时,发觉有必要较为系统地看看CG。看书评,知国人写得较好的图形学教材有唐荣锡的《计算机图形学教程》和彭群生的《计算机真实感图形的算法基础》,浙大的CAD&CG国家key lab不乏牛人。国外有一大堆经典就不说了。

着色语言(shading language)的学习是看《OpenGL着色语言》、NVIDIA的“The Cg Tutorial”和康玉之大牛的《GPU编程与Cg语言之阳春白雪下里巴人》——向康大牛致敬!——不知他近况如何。

还有是随手翻翻了一些经典,如“GPU Gems”系列,也对OpenGPU论坛热衷过一段时间,现在也偶尔去逛逛。这样到现在,算是对CG不再陌生了,但水平很一般。

言归正传!

Ray tracing通常译作“光线跟踪”,而ray casting通常译作“光线投射”。个人觉得两者区别不是很大。Ray tracing是逆向跟踪射入virtual camera的光线,在光线与场景物体的交点处累积来自光源的直接辐照量和反射、折射而来的间接辐照量;而ray casting是向三维数据场投射出光线,然后沿着光线方向积分,数值化方法为由前往后或由后向前合成。

 

图3 ray casting

图4 ray tracing

 

4.       体绘制的加速技术

体绘制处理的是海量的数据,如何提高效率是难题。体绘制的加速技术可以分为:软件加速和硬件加速。

软件加速技术有提前光线终止(early ray termination)、空间跳跃(empty space leaping)和延迟渲染(deferred shading)等。这里,空间跳跃的实现,需要对三维数据场进行数据结构管理,如八叉树、二叉树和k-d树,类似于场景管理技术。

硬件加速技术有并行实现、专用硬件实现和GPU加速。其实说GPU加速也欠妥,因为这个概念是NVIDIA在1999年才提出来的。先概述GPU加速的过去与现状吧。——了解科技史,也是学习中必不可少的一环,如:学习编程就应该去了解Unix/C的历史。

最开始是基于二维纹理映射的方法:在虚拟的三维画布上设定好一个组正方形的坐标,然后把切片图像当作纹理贴上去,最后就可以按照一定的规则得到合成图像。

 

图5 基于二维纹理映射的方法

然后是基于三维纹理映射的方法:也是先设定代理几何体,不过这时代理几何体可以垂直于观察方向。

 

图6 基于三维纹理映射的方法

随着GPU的渲染管线由固定到可编程的转变,基于纹理映射的方法可以有更多的自由度,能够实现一些复杂的光照效果,而把ray casting由CPU移植到GPU也成为可能。

这几年出现GPGPU:GPU里的众核(就是众多的计算核心)可以用作并行计算。NVIDIA适时地推出CUDA,使得基于CUDA加速体绘制一时成为热点。

 

5.       基于CUDA实现Ray-Casting

在CUDA SDK里有这样的例程。Heresy大牛写的“CUDA Volume Rendering”对此作了详细的介绍。下面我多此一举,加个流程图吧。

 

图7 CUDA-based ray-casting算法流程图

传递函数:input为表征3D数据场中重采样点的属性值,如灰度值、梯度值和曲率等;output为重采样点处的光照属性值,如不透明度、颜色等。传递函数实质上是对3D数据场的分类,是可视化技术中的十大难题之一。1D传递函数(灰度—不透明度,和灰度—颜色值)效果有限,增加维度(如梯度值)设计高维传递函数可以更好地区分开各种物质,而当前的研究热点是先用模式分类的方法识别出3D数据场中的感兴趣部分。

 

图8 一维传递函数

 

图9 二维传递函数

【注】重采样:对离散3D数据场的采样,常用三线性插值,而为了更精确复原重采样点处的信息,可以使用复杂度更高的算法,如B样条插值。

 

6.       后话

Ray casting的最后一步是由前往后或由后向前。这可以理解成简单的融合——可以参照“Jim Blinn’s Corner”中的“compositing”两篇文章,也可以理解成光线吸收—发射模型中光照积分的离散方法。这个问题在接下来探讨预积分(pre-integration)的文章会有更详细的讲述。

上文对光照模型说得很少。这可以参照“Real-Time Volume Graphics”。Joe Kniss曾经在体绘制领域活跃过几年,也做了不少重量级的贡献。他用基于三维纹理映射的方法,实现了阴影和多重散射效果。在一系列的关于“Advanced Illumination Techniques for GPU Raycasting”的conference tutorials中,Christof Rezk Salama具体阐述了他在raycasting中添加多重散射效果的方法。他是渲染多个等值面,在等值面之间计算多重散射,分为多个pass,并在“first hit pass”中计算local illumination和ambient occlusion。Christof Rezk Salama的想法源于Joe Kniss。

我想,这两种实现做了很有意义的探索,而未来将会——现在大概也有了——是先用模式识别分类好物质,然后实现各种各样的光照效果。

【注】统称为“Advanced Illumination Techniques for GPU Raycasting”的tutorials其实都一样,只是在不同的conference中有不同的名字。这个tutorials还讲述了体数据结构的组织、多分辨率绘制和多规模数据处理等。

【注】听说Joe Kniss跑去做模式识别了,不知真否。

 

图10 Joe Kniss's

 

图11 Christof Rezk Salama's

 

7.       参考文献

在上面已经提及了不少,这里就略去了

光线跟踪计算机算法的一般描述

为了生成在三维计算机图形环境中的可见图像,光线跟踪是一个比光线投射或者扫描线渲染更加逼真的实现方法。这种方法通过逆向跟踪与假象的照相机镜头相交的光路进行工作,由于大量的类似光线横穿场景,所以从照相机角度看到的场景可见信息以及软件特定的光照条件,就可以构建起来。当光线与场景中的物体或者媒介相交的时候计算光线的反射、折射以及吸收。

光线跟踪的场景经常是由程序员用数学工具进行描述,也可以由视觉艺术家使用中间工具描述,也可以使用从数码相机等不同技术方法捕捉到的图像或者模型数据。

由于一个光源发射出的光线的绝大部分不会在观察者看到的光线中占很大比例,这些光线大部分经过多次反射逐渐消失或者至无限小,所以对于构建可见信息来说,逆向跟踪光线要比真实地模拟光线相互作用的效率要高很多倍。计算机模拟程序从光源发出的光线开始查询与观察点相交的光线从执行与获得正确的图像来说是不现实的。

这种方法的一个明显缺点就是需要假设光线在观察点处终止,然后进行逆向跟踪。在一定数量的最大反射之后,最后交点处的光线强度使用多种算法进行估计,这些算法可能包括经典的渲染算法,也可能包括如辐射着色这样的技术。

光线跟踪计算机算法及其起源的详细描述

自然现象

在自然界中,光源发出的光线向前传播,最后到达一个妨碍它继续传播的物体表面,我们可以将“光线”看作在同样的路径传输的光子流,在完全真空中,这条光线将是一条直线。但是在现实中,在光路上会受到三个因素的影响:吸收反射折射。物体表面可能在一个或者多个方向反射全部或者部分光线,它也可能吸收部分光线,使得反射或者折射的光线强度减弱。如果物体表面是透明的或者半透明的,那么它就会将一部分光线按照不同的方向折射到物体内部,同时吸收部分或者全部光谱并发出辐射。吸收、反射以及折射的光线都来自于入射光线,而不会超出入射光线的强度。例如,一个物体表面不可能反射 66% 的输入光线,然后再折射 50% 的输入光线,因为这二者相加将会达到 116%。这样,反射或者折射的光线可以到达其它的物体表面,同样,吸收、反射、折射的光线重新根据入射光线进行计算。其中一部分光线通过这样的途径传播到我们的眼睛,我们就能够看到最终的渲染图像及场景。

光线投射算法

Arthur Appel 于 1968 年首次提出用于渲染的光线投射算法。光线投射的基础就是从眼睛投射光线到物体上的每个点,查找阻挡光线的最近物体,也就是将图像当作一个屏风,每个点就是屏风上的一个正方形。通常这就是眼睛看到的那个点的物体。根据材料的特性以及场景中的光线效果,这个算法可以确定物体的浓淡效果。其中一个简单假设就是如果表面面向光线,那么这个表面就会被照亮而不会处于阴影中。表面的浓淡效果根据传统的三维计算机图形学的浓淡模型进行计算。光线投射超出扫描线渲染的一个重要优点是它能够很容易地处理非平面的表面以及实体,如圆锥球体等。如果一个数学表面与光线相交,那么就可以用光线投射进行渲染。复杂的物体可以用实体造型技术构建,并且可以很容易地进行渲染。

位于纽约 Elmsford, New York Mathematical Applications Group, Inc.(MAGI)的科学家首次将光线投射技术用于生成计算机图形。1966 年,为了替美国国防部计算放射性污染创立了这个公司。MAGI 不仅计算了伽马射线如何从表面进行反射(辐射的光线投射自从二十世纪四十年代就已经开始计算了),也计算了它们如何穿透以及折射。这些研究工作帮助政府确定一些特定的军事应用;建造能够保护军队避免辐射的军用车辆,设计可以重入的太空探索交通工具。在Philip Mittelman 博士的指导下,科学家们开发了一种使用同样基本软件生成图像的方法。1972 年,MAGI 转变成了一个商业动画工作室,这个工作室使用光线投射技术为商业电视、教育电影以及最后为故事片制作三维计算机动画,他们全部使用光线投射制作了Tron 电影中的绝大部分动画。MAGI 于 1985 年破产。

光线跟踪算法

下一个重要的研究突破是 Turner Whitted 于 1979 年做出的。以前的算法从眼睛到场景投射光线,但是并不跟踪这些光线。当光线碰到一个物体表面的时候,可能产生三种新的类型的光线:反射、折射与阴影。光滑的物体表面将光线按照镜像反射的方向反射出去,然后这个光线与场景中的物体相交,最近的相交物体就是反射中看到的物体。在透明物质中传输的光线以类似的方式传播,但是在进入或者离开一种物质的时候会发生折射。为了避免跟踪场景中的所有光线,人们使用阴影光线来测试光线是否可以照射到物体表面。光线照射到物体表面上的某些点上,如果这些点面向光线,那么就跟踪这段交点与光源之间的光线。如果在表面与光源之间是不透明的物体,那么这个表面就位于阴影之中,光线无法照射。这种新层次的光线计算使得光线跟踪图像更加真实。

光线跟踪的优点

光线跟踪的流行来源于它比其它渲染方法如扫描线渲染或者光线投射更加能够现实地模拟光线,象反射和阴影这样一些对于其它的算法来说都很难实现的效果,却是光线跟踪算法的一种自然结果。光线跟踪易于实现并且视觉效果很好,所以它通常是图形编程中首次尝试的领域。

光线跟踪的缺点

光线跟踪的一个最大的缺点就是性能,扫描线算法以及其它算法利用了数据的一致性从而在像素之间共享计算,但是光线跟踪通常是将每条光线当作独立的光线,每次都要重新计算。但是,这种独立的做法也有一些其它的优点,例如可以使用更多的光线以抗混叠现象,并且在需要的时候可以提高图像质量。尽管它正确地处理了相互反射的现象以及折射等光学效果,但是传统的光线跟踪并不一定是真实效果图像,只有在非常近似或者完全实现渲染方程的时候才能实现真正的真实效果图像。由于渲染方程描述了每个光束的物理效果,所以实现渲染方程可以得到真正的真实效果,但是,考虑到所需要的计算资源,这通常是无法实现的。于是,所有可以实现的渲染模型都必须是渲染方程的近似,而光线跟踪就不一定是最为可行的方法。包括光子映射在内的一些方法,都是依据光线跟踪实现一部分算法,但是可以得到更好的效果。

光线穿过场景的反方向

从眼睛发出光线到达光源从而渲染图像的过程有时也称为后向光线跟踪,这是因为它是实际光线传播方向的反方向。但是,对于这个术语来说还有一些混淆的地方。早期的光线跟踪经常是从眼睛开始,James Arvo 等早期研究人员用后向光线跟踪表示从光源发出光线然后收集得到的结果。因为如此,将它们分成基于眼睛或者基于光源的光线跟踪将会更加清楚。在过去的几十年中,研究人员已经开发了许多组合了这两种方向的计算方法与机制以生成投降或者偏离交叉表面的或多或少的光线。例如,辐射着色算法通常根据光源对于表面的影响进行计算并且存储这些结果,然后一个标准的递归光线跟踪器可以使用这些数据生成场景的真实、物理正确的图像。在全局照明算法如光子映射以及Metropolis light transport 中,光线跟踪只是一个用来计算光线在表面之间传输的简单工具。

上面的内容转载自:http://zh.wikipedia.org/wiki/%E5%85%89%E7%BA%BF%E8%B7%9F%E8%B8%AA#.E5.85.89.E7.BA.BF.E6.8A.95.E5.B0.84.E7.AE.97.E6.B3.95

=====================================================================================

光线投射算法:

 

 

光线追踪:

 

光线投射法用于非真实感渲染;光线跟踪法用于真实感渲染。

 //

 //


一个使用CUDA来计算光线追踪的演示,改实现采用了KDTree算法,在GTX280下可以实现14MRays/second的速度,此Demo包含了源代码 近日Nvidia公司也在I3D 2009上展示了一个名为NVIRT的光线追踪引擎,同样是基于CUDA实现的

一个使用CUDA来计算光线追踪的演示,改实现采用了KDTree算法,在GTX280下可以实现14MRays/second的速度,此Demo包含了源代码

近日Nvidia公司也在I3D 2009上展示了一个名为NVIRT的光线追踪引擎,同样是基于CUDA实现的

 

Source code (2.2 MBytes)
Executable and data (41.2 MBytes)

点击查看原文

    原文作者:edgelee
    原文地址: https://blog.csdn.net/lixiaoguang20/article/details/70172136
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。