八 Unity 渲染教程:反射

环境贴图
目前 , 我们的着色器通过组合物体表面上的环境光、漫反射光和镜面反射光来对片段进行着色 。这至少对于比较阴暗的表面,会产生看上去比较真实的图像但是对于自发光的表面会看起来不太对 。
一些闪亮的表面比如说是镜子,特别是金属材质的时候 。一个完美的镜子会反射所有的光 。这意味着根本没有漫反射 。只有镜面反射的存在 。所以 , 让我们把我们的材质变成一个镜子材质,通过设置“金属”属性为1和”光滑度“属性为0.95 。同时把这个材质的颜色设置为白色 。
一个发光的白色金属球
这么做以后,得到的结果是几乎完全黑色的表面,即使它的颜色是白色的 。我们只看到一个小亮点,这是光源照射到物体直接反生发射到我们视野中的部分 。而其他所有光被反射在不同的方向 。如果你要将“平滑度“属性增加到1,那么高亮会消失 。
这看起来不像是真正的镜子 。镜子不是黑色,它们会发射东西!在这种情况下 , 它应该发射天空盒,显示一个蓝色的天空与灰色的地面 。
间接的镜面高光
我们的球变成了黑色,因为我们只包括了直接光照 。为了反射环境,我们还必须包括间接光照 。具体来说,间接光照用于镜面反射 。在函数中,我们配置了Unity的结构 。到目前为止,我们已将其镜面分量设置为零 。这就是为什么球会变成黑色!
将场景的环境亮度设置为零,以便我们可以专注于反射部分 。将我们的材质再次变成比较阴暗的非金属,平滑度为0.5 。然后将间接镜面高光颜色更改为一个更加明显的颜色 , 比如说是红色 。
(本文代码均为截图,可点击图片放大查看)
间接高光颜色分别是黑色和红色的对比图 , 光滑度是0.5
球体这次使用的是一个红色的色调 。在这种情况下,红色的深浅正好是反射率的指示 。因此,我们的球体会从它的中心那块反射一些环境光到我们的视野之中 。显然,它更多地会在它的边缘的地方发生反射 。这是因为当视角变得更浅的时候,每个表面都会变得更具有反射性 。在掠射角的情况下,大多数光被反射,一切物体都变成了镜子 。这被称为菲涅耳反射 。我们使用版本来为我们进行计算 。
表面越平滑,菲涅尔反射越强 。当使用非常高的平滑度的时候,红色环变得非常明显 。

八  Unity 渲染教程:反射

文章插图
光滑度0.15和0.95的对比图
因为反射来自间接光 , 所以它与直接光源无关 。这样的话,反射也与该光源的阴影无关 。因此,菲涅耳反射在球体的被遮蔽的边缘中变得非常明显 。
在金属的情况下,间接反射占主导地位 。不再是一个黑色的球体 , 我们现在得到一个红色的球体 。
光滑度0.15、0.50和0.95的金属材质对比图
对环境进行采样
为了反射出实际的环境,我们必须对天空盒的立方体贴图进行采样 。它在中定义为 。这个变量的类型取决于在中确定的目标平台 。
使用三维向量对立方体贴图进行采样,这可以指定采样的方向 。我们可以使用宏来处理类型上差异 。让我们在开始的时候只使用法线向量作为采样的方向 。
对环境进行采样
天空盒出现在我们的球体上了,但是这太亮了 。这是因为立方体贴图里面包含高动态范围颜色,这允许它包含大于1的亮度值 。我们必须将样本从高动态光照渲染格式转换为RGB 。
包含一个函数,我们可以使用它 。高动态光照渲染数据存储在四个通道之中,使用的是RGBM格式 。所以我们必须采样一个值,然后进行转换 。
高动态光照渲染数据解码以后的效果
八  Unity 渲染教程:反射

文章插图
是什么样子?
RGBM格式包含RGB三个通道,加上包含幅度因子的M通道 。最终的RGB值是通过将它们乘以
来计算 。在这个公式里面,x是标量,y是指数,分别存储在解码指令的前两个分量中 。
包含幅度因子的M通道的转换是必须的,这是因为当存储在纹理中的时候,会限制使用8位值来表示一个0到1范围 。因此,x指令将其放大,y指令使其非线性,比如像是伽马空间那样 。
跟踪反射
我们得到了正确的颜色,但是我们没有看到实际的反射 。这是因为我们使用球体的法线来对环境进行采样,所以投影不依赖于视图方向 。所以它就像在一个球体上涂上了环境贴图一样 。
为了产生实际反射,我们必须得到从相机到物体表面的方向,并使用表面法线来反射它 。我们可以使用函数,就像我们在这个系列的第4部分所做的那样 。在这种情况下 , 我们需要视图方向,因此将其作为参数添加到 。
使用法线和反射方向之间的对比
使用一个反射探测器
让物体能反射天空盒很好 , 但如果能反射实际场景几何的话就更好了 。所以让我们创建一个简单的建筑 。我使用一个旋转后的四边形作为一个地板,并在它的上面放置了几个立方体柱 , 以及一些立方体梁 。球体位于建筑物的中心 。
【八Unity 渲染教程:反射】有一些东西等待反射
要看到建筑物的反射,我们必须先捕获它 。这是通过反射探测器完成的,你可以通过 / Light /Probe进行添加 。创建一个反射探测器并将其放置在与我们的球体相同的位置 。