阴影玩具路径跟踪:菲涅耳、粗糙折射和吸收、轨道相机

2020-06-16 12:15:09

下面是反射最小的球体(反射几率!)。为0.02,则IOR从1(左侧)到2(右侧)。对我来说,右边的那个看起来像一颗珍珠。(这是着色器玩具中的场景定义值2场景)。

除此之外,";IOR";的浮点也需要添加到SMaterialInfo。这是上一章末尾的场景,使用菲涅耳,所有东西都使用IOR 1.0。

这是上一章中没有菲内尔的场景。差别非常细微,因此您可能希望在浏览器选项卡中打开每个图像以来回翻转。最大的区别在于黄色和粉色球体的边缘。菲涅耳对稍微有光泽的对象产生了最大的不同。非常有光泽或完全没有光泽的物体不会有明显的菲涅尔效果。

在上一篇文章中,我们使用了一个随机数来选择反射光线是漫反射光线还是镜面反射光线,并对镜面反射的概率进行了测试。

在这样做的时候,我们应该将吞吐量除以实际选择射线的概率(以不使一条射线在最终平均值中比另一条更多),但我们没有这样做。这是一个“数学细节”,但是很容易随便放进去,所以让我们做正确的事情。

根据随机滚动找到设置点镜面反射浮点的位置。把这个放在下面:

与上图最大的不同之处在于粉色和黄色的球体稍微变亮了一点,当然它们的反射也是如此!

好玩的时间到了!我们将在这一节中讨论这些特性并显示结果,然后在下一节中展示如何将它们放入路径跟踪器中。

关于第二个…的最后一篇帖子的思考。在简单渲染和旧式光线跟踪器中,反射的工作原理是使用Reflect()公式/函数来查找光线击中曲面的最锐利的镜面反射角,并跟踪该光线。在上一篇文章中,我们展示了如何向反射光线注入一些随机性,方法是使用材质粗糙度值在完全反射的光线和法线定向半球上的随机光线之间进行细微调整。

对于简单渲染和旧式光线跟踪器,有一个refract()公式/函数,该公式/函数为光线击中曲面找到一个非常锐利的折射角度,其中该曲面具有特定的IOR(折射率)。与菲涅耳使用的参数相同)。唯一的区别是,由于折射光线穿过对象而不是反射对象,因此随机半球将以曲面的负法线为方向。

下面是折射球从左侧的IOR 1到右侧的1.5的图像。请注意,随着IOR的增加,背景是如何扭曲的,还要注意球体下面的灯光是如何聚焦的。这些都是“焦散”,对于其他形状的网格会变得更加有趣。(这是着色器玩具中的场景定义值1)。

你可能会注意到中间球体下面的地面上有一些黑色的条纹。当我第一次看到这些时,我以为这是一个bug,但通过实验发现,它们实际上是天空(天盒顶部)中的图像的投影。

为了进一步演示这一点,这里有一个场景,其中球体都具有相同的IOR,但它们与地面的距离不同,这会聚焦/散焦通过球体投影的图像,以及球体上方的灯光。(着色器玩具中的场景定义值4)。

换个天箱,看起来是这样的。注意到左边地面上的投影有那个圆形吗?

抬头看球体上方的东西,你可以看到投射到地面上的那个圆圈。这是关于路径跟踪…最酷的事情之一。你可以“免费”获得很多技巧,这些技巧只是数学中的新兴特征。这与在光栅化/非路径跟踪渲染中接近图形有很大不同,在这种情况下,每个您想要的功能,您基本上都必须为其编写显式代码才能近似。

回到粗糙度,下面是一些使用IOR 1.1的折射球体,但粗糙度从左侧的0到右侧的0.5不等。请注意,球体本身明显变得更加粗糙,但其阴影/焦散也会随粗糙度变化。(着色器玩具中的场景定义值6)

重要的是要注意到,在这些情况下,只有球体的表面才有任何粗糙度。如果你能拿出这些球中的一个,把它劈成两半,里面就会完全光滑和透明。在未来的帖子中(我想是下一个!)。我们将讨论如何在对象内部制作一些粗糙度,这也是如何渲染烟雾、雾、云以及皮肤、牛奶和蜡之类的东西。

你可以添加到透明物体上的另一个有趣的功能是“吸收”,这意味着光线在穿过物体时会被吸收一段距离。

我们将利用比尔定律,得到通过物体的光的乘数,从而使光减少。这个公式就是这样的:

为此,我们可以对每个颜色通道使用不同的吸收值,以便当光线穿过对象时,不同的颜色吸收得更快或更慢。

下面是一些吸收程度逐渐提高的球体。百分比倍增从左侧的0到右侧的1,并乘以(1.0,2.0,3.0)以获得吸收值。请注意球体如何更改,但焦散/阴影也是如此。这是着色器玩具中的场景定义值3。

你可以把粗糙度和专注度结合起来,做出一些有趣的东西。下面是相同的球体,但有一些吸收(场景定义值0)。

下面是来自不同视图的相同场景,其中显示了这些对象的着色是多么丰富。

您可能会注意到,既有镜面粗糙度也有折射粗糙度。如果需要,可以将它们组合成一个单独的“表面粗糙度”,供两者使用。你失去了使反射具有与折射不同的粗糙度的能力,但这不会是一个巨大的损失。

此外,还有镜面反射机会和折射机会,隐含漫反射机会使其总和为1.0。

与其那样做机会,另一件可以尝试的事情是使漫反射机会是反照率成分的总和,镜面反射机会是镜面反射颜色成分的总和,折射机会是折射颜色成分的总和。然后你可以将它们全部除以所有3次机会的总和,这样它们的总和就是1.0。

这将使您摆脱这些百分比,应该是相当不错的选择。唯一奇怪的是,与其他颜色相比,折射颜色的含义有点颠倒。其他是让多少光通过,但折射颜色是阻挡多少光。您可能会更幸运地从(1,1,1)中减去折射颜色,并使用它来产生折射机会。

由于光线的灯光除以选择该类型光线(漫反射、镜面反射或折射)的概率,因此如何选择用于选择光线类型的概率实际上并不重要,但是当概率与像素最终颜色的贡献更好地匹配时(贡献越多=百分比越高),您将更快地获得更好(更收敛)的图像。这是直接的重要抽样,我就到此为止,这样我们就可以保留这个随意的🙂。

下一个变化是解决我们可能遇到的一个问题。现在我们的材质有相当多的组件,在设置材质属性时很容易忘记设置一个组件。如果您曾经忘记设置一个值,您将具有未初始化的值,或者来自先前光线命中的值不再有效。这将使一些真正难以跟踪的bug以及由于未初始化值(AFAIK)而导致的未定义行为的可能性随之而来。所以,我做了一个函数,它将材料初始化为大致为零,但主要是为了合理的值。其思想是调用此函数来初始化材质,然后设置您关心的特定值。

每次设置材质信息(例如,每次光线交叉点通过时),我首先调用此函数,然后设置我关心的特定值。当我第一次在GetColorForRay()中声明SRayHitInfo结构本身时,我也会调用它。

接下来,还要向SRayHitInfo添加一个bool“from mInside”。我们需要这个,才能知道当我们与一个物体相交时,我们是从内部还是从外部击中它。折射使我们可以进入物体内部,我们现在需要知道这是什么时候发生的。

在修改光线命中信息的TestQuadTrace()中,确保将from Inside设置为false。我们要说的是,四合院是没有内部的。你可以让四边形的负面(基于它的正常)在里面,也许可以用四边形建造盒子等等,但我决定不去处理这个复杂的问题。

TestSphereTrace()已经具有光线是否从内部击中球体的概念,但它不会将其公开给调用者。我只是让它根据已经存在的Inside bool设置来自Inside bool的光线命中信息。

粗糙度和镜面反射百分比的各种用途需要更改为specularRough和specularChance。

回弹循环内的最终着色改变了很多,所以我将在下面粘贴这个,但是它的注释很重,所以希望它是有意义的。

我认为最值得解释的是吸收是如何发生的。我们不知道当我们进入一个物体时会发生多少吸收,因为我们不知道光线会穿过这个物体多远。正因为如此,我们不能更改吞吐量来考虑进入对象时的吸收。取而代之的是,我们需要等待,直到我们击中物体的远侧,然后才能计算吸收并更新吞吐量来解释它。看待这一问题的另一种方式是“当我们从内部击中物体时,这意味着我们应该计算和应用吸收”。这还可以处理光线在离开之前可能在对象内部多次反弹的情况(由于对象内部发生的镜面反射和菲涅尔)-每次内部镜面反射反弹时都会计算并应用吸收。

现在我们可以做所有这些很酷的渲染了,相机卡在一个地方有点糟糕。

能够移动相机,从不同的角度看东西,真的很有趣。它在调试方面也很有帮助--就像我们能看到天箱天花板上的圆圈一样!

首先将此函数拖放到Buffer A选项卡中,就在mainImage函数的正上方。您可以将常量留在那里,也可以将它们放在公共选项卡中,无论您愿意做什么。

mainImage函数在RNG的播种和光线跟踪之间也有相当大的变化-基本上是控制TAA的抖动和计算相机向量的东西。下面是整个函数,希望有足够好的注释来理解。

完成此操作后,您可以在图像中拖动鼠标左键在🙂周围移动相机。

如果你按照这些步骤从上一篇文章的场景,并改变中心球体到一点折射,你终于可以从一个不同的角度查看长方体!

在我们开始之前,我想展示一些折射球,折射率为1,折射粗糙度为0,但在左侧的纯折射表面和右侧的纯漫反射表面之间渐变。这是着色器玩具中的场景定义值5。

将此场景与前面显示的纯吸收场景和纯粗糙场景进行比较。

随着效果的显现,这三个人都更多地掩盖了他们背后的东西。所有这些措施也可能在任何程度上产生部分有效的效果。

当我们在光栅化的场景中进行传统的Alpha混合时,我们谈论的是这些中的哪一个?

如果半透明对象的阴影是彩色的,这意味着吸收是它的最佳模型。如果半透明对象的阴影刚刚变暗,部分漫反射表面可能是最好的模型(也可能是吸收)。如果对象没有投射阴影(或几乎没有投射),则它是由于对象表面或对象内部的粗糙度而变得半透明的对象(我们稍后将讨论这种情况)。如果对象的外观(照明)与仅从前面照明的对象相比,在其后面(或周围)的照明发生显著变化时,情况尤其如此。

把alpha看作所有这些不同的效果是一件奇怪的事情,但如果做真实的渲染,也能意识到这一点也是件很好的事情。

哦,PS-我曾经从一位艺术家那里得到的一个颜色提示是永远不要使用纯原色(我想是罗恩·哈维@Monolith)。如果您正在阅读这篇文章,Ron,您好!)。从艺术的角度来看,这很好,但是,如果您考虑照明是如何乘以这些不同的颜色的,那么每当您设置任何颜色通道0时,这意味着没有一个颜色通道能够通过该倍增。完全扼杀任何类型的光都会让人感觉不对,而且确实会让事情看起来微妙地错误(或不微妙!),因为现实世界中没有任何东西是如此完美或纯粹,以至于它不会反射出与其主频或多个频率不同的一些光。如果它如此纯净,尘土就会落在它上面,并改变这一点。此外,出于类似的原因,远离1可能是个好主意--没有什么能完美地反映现实世界中的任何东西,总会有一些不完美的地方--同样,如果是这样的话,灰尘会落在它上面,并改变它。

谢谢你的阅读,我很想看看你做的任何东西。你可以通过@Atrix256找到我