ntroduction to Ray Tracing: a Simple Method for Creating 3D Images

ray-tracing algorithm :光线跟踪算法

这个算法是模拟使物体可见的物理现象的最直接的方法。
首先,我们将使用光线跟踪算法奠定基础。然而,一旦我们涵盖了所有的信息,我们需要实现扫描线渲染器

Perspective Projection:透视投影

在二维平面上画出三维物体的轮廓

Light and Color: 光线和色彩

在一个场景中,物体的颜色和亮度主要是光线与物体材料相互作用的结果。光是由光子(电磁粒子)组成的,换句话说,光子有一个电分量和一个磁分量。它们携带能量,像声波一样在直线中振荡。光子是由各种各样的光源发出的,最著名的例子是太阳。如果一组光子击中一个物体,会发生三种情况:它们要么被吸收,要么被反射,要么被传输。从一种材料到另一种材料,反射、吸收和传输的光子比例各不相同,通常决定了物体在场景中的表现。然而,所有物质都有一个共同的规则,即入射光子的总数总是等于反射、吸收和透射光子的总数。
为了简单起见,我们假设吸收过程决定了物体的颜色。白光由“红色”、“蓝色”和“绿色”光子组成。如果白光照亮了红色物体,吸收过程会过滤掉(或吸收)“绿色”和“蓝色”光子。因为物体不吸收“红色”光子,它们被反射。这就是这个物体呈现红色的原因。

在计算机图形学中,从光或从眼睛发射光线的概念称为路径跟踪 forward ray-tracing:前向光线追踪

在这里插入图片描述

首先,我们用一个由像素组成的图像平面来代替我们的眼睛。在这种情况下,发出的光子将击中图像平面上的许多像素中的一个,从而将该点的亮度增加到大于零的值。这个过程重复多次,直到所有的像素都被调整,创建一个计算机生成的图像。这种技术称为前向光线追踪,因为我们沿着光子从光源到观察者的路径前进。
问题:
问题如下:在我们的例子中,我们假设反射的光子总是与眼睛表面相交。在现实中,光线基本上反射在每一个可能的方向,每一个都有一个非常,非常小的可能性击中眼睛。我们可能不得不从光源投射出无数的光子,才能找到一个能击中眼睛的光子。事实上,这就是它的工作原理,无数光子以光速向四面八方传播。在计算机世界中,模拟场景中那么多光子与物体的相互作用是不现实的解决方案,原因如下:

所以你可能会想:“我们真的需要向随机方向发射光子吗?”既然我们知道眼睛的位置,为什么不直接向那个方向发射光子,看看它通过图像中的哪个像素,如果有的话?”这当然是一种可能的优化方法,但是我们只能对某些类型的材料使用这种方法。由于我们将在以后的光与物质相互作用的课程中解释的原因,方向性对漫反射表面并不重要。这是因为一个光子击中一个漫反射表面可以在任何方向反射半球中心周围的法线在接触点。但是,如果表面是一面镜子,并且没有漫反射的特性,光线只能在一个非常精确的方向上反射;镜像方向(我们稍后将学习如何计算)。对于这种类型的表面,我们不能决定人为地改变光子的方向,如果它实际上应该遵循镜像的方向。这意味着这个解决方案不是完全令人满意的。
即使我们决定使用这种方法,在一个只有漫反射物体的场景中,我们仍然会面临一个主要的问题。我们可以想象将光子从光发射到场景中的过程,就像你在物体表面上喷洒光线(或油漆的小颗粒)。如果喷雾的密度不够大,有些地方就不能均匀地照明。

但是发射1000个光子,甚至是X倍,都不能真正保证我们的物体表面完全被光子覆盖。这是这项技术的一个主要缺点。换句话说,我们可能不得不让程序运行,直到我们确定它已经在物体表面喷射了足够多的光子,以获得它的精确表示。这意味着我们需要在呈现图像时观察它,以便决定何时停止应用程序。在生产环境中,这是不可能的。另外,正如我们将要看到的,在光线追踪器中最昂贵的任务是寻找光线与几何图形的交点。从光源中产生许多光子不是问题,但是,必须在场景中找到它们所有的交叉点将是非常昂贵的。

结论:前向光线追踪(或光线追踪,因为我们从光中射出光线)使得在计算机上模拟光在自然界中传播的方式在技术上成为可能。然而,正如所讨论的,这种方法既不有效也不实用。
“光线追踪的一种明显方法是,追踪光源发出的光线的路径,直到光线击中观察者。由于只有少数几个将到达观众,这种方法是浪费。

Backward Tracing:眼睛追踪(后向光线追踪)

在这里插入图片描述
我们不是追踪光线从光源到受体(如我们的眼睛),而是追踪光线从受体到物体。因为这个方向与自然界中所发生的相反,所以它被恰当地称为反向射线追踪或眼睛追踪,因为我们是从眼睛的位置发射光线的?(图2).该方法为解决前向射线追踪的缺陷提供了方便的解决方案。由于我们的模拟不可能像自然那样快速和完美,我们必须妥协,从眼睛到场景中追踪一束光线。如果射线击中了一个物体,那么我们就可以通过将另一束射线(称为光或阴影射线)从命中点投射到场景的光中来计算出它接收了多少光。偶尔这道“光线”会被场景中的另一个物体挡住,这意味着我们最初的生命点在阴影中;它不接受任何来自光的照明。由于这个原因,我们不给这些射线命名为光线?而是影子射线。在CG文献中,我们从眼睛射入场景的第一束光线被称为主射线,可见射线,或相机射线。

光线追踪算法采用像素构成的图像。对于图像中的每个像素,它都向场景发射一束主光线。主光线的方向是通过从眼睛到像素中心的一条线来获得的。一旦我们有了主射线的方向集,我们检查场景中的每一个物体,看看它是否与它们中的任何一个相交。在某些情况下,主射线会与多个物体相交。当这种情况发生时,我们选择其交点最接近眼睛的物体。然后,我们从交点射向光的阴影射线(图6,上图)。如果这条特定的射线在它到达光的路上没有与一个物体相交,那么这个生命点就被照亮了。如果它确实与另一个对象相交,则该对象会在其上投射阴影(图2)。

在这里插入图片描述
在这里插入图片描述
正如我们所看到的,射线追踪的美妙之处在于,只需几行代码即可完成;一个人当然可以用200行写一个基本的射线追踪器。与其他算法(如扫描线渲染器)不同,光线跟踪只需很少的努力就可以实现。正如阿佩尔在他的论文中提到的:这种方法非常耗时,通常需要的计算时间是一幅线框图的数千倍。大约一半的时间用于确定投影和场景的点对点对应关系。”

找到射线和几何图形之间的交点是非常耗时的。几十年来,该算法的速度一直是光线追踪的主要缺点。然而,随着计算机变得越来越快,这个问题就越来越少了。尽管有一点必须说明:与其他技术(如z-buffer算法)相比,射线跟踪仍然要慢得多。然而,今天,有了快速的计算机,我们可以计算一个帧,过去需要一个小时在几分钟或更少。事实上,实时和交互式的射线追踪器是一个热门话题。
总之,重要的是要(再次)记住,呈现例程可以看作两个独立的进程。一个步骤确定一个点在一个特定的像素上是否可见(可见部分),第二个步骤确定该点的阴影(阴影部分)。不幸的是,这两个步骤都需要昂贵且耗时的射线几何相交测试。这个算法优雅而强大,但它迫使我们牺牲渲染时间来换取准确性,反之亦然。自从阿佩尔发表了他的论文以来,人们做了大量的研究来加速光线-物体的相交例程。通过将这些加速方案与计算机中的新技术相结合,光线追踪变得更加容易,几乎所有的产品渲染软件都使用了光线追踪。

**栅格化和光线跟踪都可以用来解决可见性问题。尽管要记住渲染过程是一个两步的过程:它包括可见性和阴影。**栅格化对可见性有好处(而且比光线跟踪要快得多),但在阴影方面不如光线跟踪好。另一方面,光线跟踪可以用于这两种情况。

射线追踪听起来是一个比栅格化更好的方法,尽管射线追踪的主要问题是它涉及到计算射线与几何图形的交集,这是一个昂贵的操作(即缓慢)。在实时图形应用中,速度比真实感更重要,这就是gpu使用栅格化的原因。当真实感比速度更重要时,光线追踪是一个更好的选择,尽管在交互帧率下使用光线追踪很难产生图像,在实时帧率下就更困难了。

综上所述,使用光线追踪来计算三维物体的真实感图像,基本上可以分为三个步骤:

投射光线:为图像中的每个像素投射光线

射线-几何相交:测试一条射线是否与场景中的任何物体相交(这需要为每条投射射线遍历所有物体)。

着色:找出物体在光线和物体的交点上的“样子”(如果发生了交点)。

光线追踪的主要问题之一是,它要求所有的场景几何图形都要存储在内存中,而图像正在被渲染。这对于光栅化来说并不一定是这样的:一旦我们知道一个对象在屏幕上的任何地方都不会出现,我们就可以把它扔掉(并从内存中删除)。背对镜头的三角形也可以被丢弃,如果背对镜头的剔除操作正在进行。在光线追踪中,即使一个物体在场景中是不可见的,它也可能会在摄像机可见的物体上投射阴影,因此需要保存在内存中,直到图像中的最后一个像素被处理。由于生产场景中包含数百万个三角形,因此存储数据所需的内存可能会成为一个问题。
总之,光线追踪器通常比光栅化器使用更多的内存。射线跟踪可以生成更真实的图像,但代价是比基于栅格化算法的程序更慢,占用更多内存。该算法在概念上很简单,但在具有复杂阴影的大型复杂场景中很难可靠、有效地工作。

反射和折射

反射和折射方向取决于:
法向量和入射光线的方向,折射还取决于材料的折射率
反射和折射的混合
我们需要同时计算曲面上的一个给定点,但是如何把它们混合在一起呢?我们要把50%的反射结果和50%的折射结果混合吗?不幸的是,实际情况要复杂得多。数值的混合取决于主射线(或观测方向)与物体法线和折射率之间的夹角。然而,对我们来说幸运的是,有一个公式可以精确地计算出每种物质应该如何混合。这个方程被称为菲涅耳方程
计算在那一点上产生的颜色;
例如,玻璃球,你需要计算反射颜色和折射颜色,并将它们混合在一起。记住,我们分三步来做。计算反射颜色,计算折射颜色,然后应用菲涅耳方程。
首先计算反射方向。我们需要两个条件:交点的法线和主射线的方向。一旦我们得到了反射方向,我们就朝那个方向发射一条新的射线。回到之前的例子,假设反射光射入红色球面。利用阿佩尔的算法,我们通过向红色球体发射阴影射线来计算到达该点的光的数量。这样就得到了一种颜色(如果阴影是黑色的),然后乘以光的强度,返回到玻璃球的表面。
递归
这个算法的一个美妙之处在于它是递归的。在我们目前学习的例子中,反射光线射入一个红色的不透明球体,折射光线射入一个绿色的不透明的漫反射球体。但是,我们可以把红色和绿色的球想象成玻璃球。为了找到反射和折射光线返回的颜色,我们必须对红色和绿色球体进行与原始玻璃球相同的处理。这是光线追踪算法的一个严重缺陷,在某些情况下,它实际上是噩梦。想象一下,我们的相机在一个盒子里,盒子里只有反光的面孔。从理论上讲,光线被捕获,并将继续不断地从盒子的墙壁上反弹(或者直到你停止模拟)。由于这个原因,我们必须设置一个任意的限制来阻止光线的相互作用,从而无休止地递归。光线每反射一次或折射一次,它的深度就增加一次。当射线深度大于最大递归深度时,我们只需停止递归过程。

in a nutshell 简而言之

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值