学习Scratchapixel--(6)光线模拟器


反射

当光线和完美的镜面接触时,我们可以预知它返回的方向。这可以用反射定律计算出来。(公式简单,不赘述)

  • 水虽然看上去像镜子,但是水和玻璃比起金属来说,只能算是很弱的镜面了。

透明度

当光线和透明物体接触时,会发生反射和折射。我们也常常用传递(transmit)来代替折射。但是这两个术语有微小的差别。传递是说,一部分入射光从一侧进入物体,并从另一侧离开。而当它一接触到透明物体的表面时,就转变了方向,而这被称为折射。

  • 折射的方向可以用斯涅尔定律(Snell's Law)计算

  • 折射的强度可以用菲涅耳公式(Fresnel's equation)计算

  • 上面两个公式相当重要

光泽反射和镜面反射

光泽反射即,当一个物体介于镜面和完全漫反射之间时。或者说其某些地方十分光滑,而某些地方粗糙时。

光泽度也被称为粗糙度(roughness)。同时光泽反射也常常被称为 镜面反射(specular reflection)

  • 在CG中,我们通常说散射(scattering),因为光线不是朝一个方向反射,而是在镜面方向附近的小范围内进行散射

漫反射

入射光线反射向各个方向,所以从哪个方向看,物体都一样亮。导致漫射表面的情况有两种:

  1. 物体表面十分粗糙
  2. 表面由微小结构组成
    光线会在这些结构中来回反射和折射无数次直到离开表面。而这使得光线的方向变得随机。

子面散射(Subsurface Scattering)

子面散射是半透明(translucency)的专业术语。半透明即一个表面处于完全透明和不透明之间。但是半透明和物体的透明度没有多少关系。我们可以清楚地观察到,用强光照射在蜡、用玉或大理石做的小件、或者是较薄的有机材质(皮肤、叶片)上时,有强烈的现象。这个相当难以模拟。

间接漫反射(Indirect Diffuse)

当光线直射到物体表面时,其会反射并照射到其他的物体,而这被称为间接照射。由于物体表面是漫射的,所以被称为间接漫反射。这使得周围未被光线照射到的地方也会被间接照亮。

间接镜面或焦散(Indirect Specular or Caustics)

像漫射物体可以反射光线并照射周围的物体一样,反光物体也可以通过重定向光线来间接照射其他物体。镜头或者水面上的波浪可以将光线聚集于特殊的线或者模式,这被称为焦散(caustics)

软阴影

软阴影和物体的材质无关。模拟软阴影只是一个几何问题,涉及到物体和光源的形状、大小和位置。

漫反射表面从任何角度看都一样亮。但是镜面表面的亮度取决于视线角度。我们称漫反射为视角无关的(view-independent),称镜面反射为视角相关的(view-dependent)

光线传输和着色:两个相关但不同的问题

理解两点:

  • 物体的外观只取决于光的传输和与物质交互的方式

  • 所有的特效都可以大致分为两类:

    • 与物体外观相关
    • 与物体接受多少光线相关

    第一种类别与着色(这给予了物体的外观)相关,其中有之前提到的反射、透明度、镜面反射、漫反射和子面散射。而第二种类别与光线传输(光如何在与不同材质交互后从一个表面传到另一个表面)相关,如间接漫反射、间接镜面、软阴影

    在着色中,我们学习光如何和物质交互。也就是说,它关注从光到达物体到离开物体这中间发生的所有事情。

    光线传输学习光如何从表面之间反射。其关注光从光源到眼睛这之间所经历的路径。

着色和光线传输的界限很模糊。在现实中它们实际上没太多区别。但是在CG中,它们不能有效地用同一种方法去模拟,所以被区分开了。

如果我们原子级地复制现实世界到电脑中,写下代码制定光与原子作用的基本规则,我们只需要等待光来回弹射直到到达我们的眼睛,这样就能生成一个完美的图像。但是现有技术无法做到。我们需要做的,是找到这个过程中最耗时的部分。显然光到达物体表面进行交互是相当复杂的,并且也是最耗时的。

所以,我们在CG中做了区分。着色是设计数学模型来接近光和物体的交互。

模拟光线运动比模拟光与物质的相互作用更简单,但也没那么简单。某些类型的互反射(inter-reflection)相当难以模拟(如焦散)。一方面,设计优秀的数学模型来模仿光与表面的交互是很难的;另一方面,设计一个优秀的光线运动算法也很有挑战性。

全局照明(global illumination)

你可能会有这样的误解,大部分表面因为从光源直接接受到光线,所以才可见。但是实际上有许多情况中,物体是被其他表面间接照明的。你可以看看在你的周围有多少物体是直接暴露在光源下的。间接光照在现实中是重要的环节,如果不模拟这个效果,那么图像将是失真的。在渲染中我们同时模拟直接和间接光照效果,这被叫做全局光照

理想状态下,在渲染中,我们想模拟所有可能的照明脚本(scenario),这取决于:

  • 场景中包含物体的形状、材质
  • 场景中有多少光量
  • 光的类型(太阳、灯泡、火焰)
  • 光的形状
  • 物体在空间中的分布

为什么我们不模拟间接光照呢?因为这将需要从视点发射更多的光线,花费大量时间计算光线和物体的交互,这中间的时间损耗甚至能达到数量级的差距。

使用光线追踪来模拟间接光照是很容易的事,你只要模拟现实世界中光线的运动就行了。但是使用栅格化来模拟十分困难,然而不是不可能。如点云技术(point cloud based),光子映射(photon mapping),虚拟点光源(virtual point light),阴影贴图(shadow mapping)。辐射度算法(Radiosity)在80年代十分流行,但是现在很少使用了。但是最简单的方法是使用光线追踪。

光线追踪对某些特殊的光照效果反而很难模拟。如间接镜面反射。而光子映射是一个设计来有效模拟焦散(间接镜面反射的一种形式)的技术。

光线追踪真的比栅格化更好么?

首先光线追踪相比栅格化是一种更接近自然的模拟技术,而且它可以同时用于解决可视性和光照问题。

光线追踪不是一个奇迹性的方案。它有自己的问题

布林定律:如果一个动画工作室花费十个小时计算一个帧的动画,那么在十年后他们也将花费十小时每帧,无论处理性能有多大的进步。

你需要积极地优化你的代码来使其具有实用性。但是如果你不去管这些技术性的问题,光线追踪的主要缺陷就在于噪声-noise(术语称为方差-variance)。而解决方法也很简单粗暴,使用更多的光线来提升模拟的质量。而光线追踪也可以与一些其他的技术相结合来提高模拟特定光照效果的效率。

你可能感兴趣的:(学习Scratchapixel--(6)光线模拟器)