Unity 渲染教程(八):反射

这篇博客详细介绍了在Unity中创建真实感反射的过程,包括设置金属材质、理解间接镜面高光、使用环境贴图、反射探测器的工作原理、对立方体贴图进行采样、处理不同光滑度的反射、模拟粗糙表面的反射以及处理多次反射。通过实例展示了如何解决反射中的问题,如使用盒体投影优化反射质量,以及如何处理静态和动态物体的反射。
摘要由CSDN通过智能技术生成

环境贴图

目前,我们的着色器通过组合物体表面上的环境光、漫反射光和镜面反射光来对片段进行着色。这至少对于比较阴暗的表面,会产生看上去比较真实的图像但是对于自发光的表面会看起来不太对。

一些闪亮的表面比如说是镜子,特别是金属材质的时候。一个完美的镜子会反射所有的光。这意味着根本没有漫反射。只有镜面反射的存在。所以,让我们把我们的材质变成一个镜子材质,通过设置“金属”属性为1和”光滑度“属性为0.95。同时把这个材质的颜色设置为白色。

一个发光的白色金属球

这么做以后,得到的结果是几乎完全黑色的表面,即使它的颜色是白色的。我们只看到一个小亮点,这是光源照射到物体直接反生发射到我们视野中的部分。而其他所有光被反射在不同的方向。如果你要将“平滑度“属性增加到1,那么高亮会消失。

这看起来不像是真正的镜子。镜子不是黑色,它们会发射东西!在这种情况下,它应该发射天空盒,显示一个蓝色的天空与灰色的地面。

间接的镜面高光

我们的球变成了黑色,因为我们只包括了直接光照。为了反射环境,我们还必须包括间接光照。具体来说,间接光照用于镜面反射。在CreateIndirectLight函数中,我们配置了Unity的UnityIndirect结构。到目前为止,我们已将其镜面分量设置为零。这就是为什么球会变成黑色!

将场景的环境亮度设置为零,以便我们可以专注于反射部分。将我们的材质再次变成比较阴暗的非金属,平滑度为0.5。然后将间接镜面高光颜色更改为一个更加明显的颜色,比如说是红色。

(本文代码均为截图,可点击图片放大查看)

间接高光颜色分别是黑色和红色的对比图,光滑度是0.5

球体这次使用的是一个红色的色调。在这种情况下,红色的深浅正好是反射率的指示。因此,我们的球体会从它的中心那块反射一些环境光到我们的视野之中。显然,它更多地会在它的边缘的地方发生反射。这是因为当视角变得更浅的时候,每个表面都会变得更具有反射性。在掠射角的情况下,大多数光被反射,一切物体都变成了镜子。这被称为菲涅耳反射。我们使用UNITY_BRDF_PBS版本来为我们进行计算。

表面越平滑,菲涅尔反射越强。当使用非常高的平滑度的时候,红色环变得非常明显。

光滑度0.15和0.95的对比图

因为反射来自间接光,所以它与直接光源无关。这样的话,反射也与该光源的阴影无关。因此,菲涅耳反射在球体的被遮蔽的边缘中变得非常明显。

在金属的情况下,间接反射占主导地位。不再是一个黑色的球体,我们现在得到一个红色的球体。

光滑度0.15、0.50和 0.95的金属材质对比图

对环境进行采样

为了反射出实际的环境,我们必须对天空盒的立方体贴图进行采样。它在UnityShaderVariables中定义为unity_SpecCube0。这个变量的类型取决于在HSLSupport中确定的目标平台。

使用三维向量对立方体贴图进行采样,这可以指定采样的方向。我们可以使用UNITY_SAMPLE_TEXCUBE宏来处理类型上差异。让我们在开始的时候只使用法线向量作为采样的方向。

对环境进行采样

天空盒出现在我们的球体上了,但是这太亮了。这是因为立方体贴图里面包含高动态范围颜色,这允许它包含大于1的亮度值。我们必须将样本从高动态光照渲染格式转换为RGB。

UnityCG包含一个DecodeHDR函数,我们可以使用它。高动态光照渲染数据存储在四个通道之中,使用的是RGBM格式。所以我们必须采样一个float4值,然后进行转换。

高动态光照渲染数据解码以后的效果

DecodeHDR是什么样子?

RGBM格式包含RGB三个通道,加上包含幅度因子的M通道。最终的RGB值是通过将它们乘以

来计算。在这个公式里面,x是标量,y是指数,分别存储在解码指令的前两个分量中。

包含幅度因子的M通道的转换是必须的,这是因为当存储在纹理中的时候,会限制使用8位值来表示一个0到1范围。因此,x指令将其放大,y指令使其非线性,比如像是伽马空间那样。

跟踪反射

我们得到了正确的颜色,但是我们没有看到实际的反射。这是因为我们使用球体的法线来对环境进行采样,所以投影不依赖于视图方向。所以它就像在一个球体上涂上了环境贴图一样。

为了产生实际反射,我们必须得到从相机到物体表面的方向,并使用表面法线来反射它。我们可以使用reflect函数,就像我们在这个系列的第4部分所做的那样。在这种情况下,我们需要视图方向,因此将其作为参数添加到CreateIndirectLight。

使用法线和反射方向之间的对比

使用一个反射探测器

让物体能反射天空盒很好,但如果能反射实际场景几何的话就更好了。所以让我们创建一个简单的建筑。我使用一个旋转后的四边形作为一个地板,并在它的上面放置了几个立方体柱,以及一些立方体梁。球体位于建筑物的中心。

有一些东西等待反射

要看到建筑物的反射,我们必须先捕获它。这是通过反射探测器完成的,你可以通过GameObject / Light / Reflection Probe进行添加。创建一个反射探测器并将其放置在与我们的球体相同的位置。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Mirror-BumpSpec.shader 实时镜面反射shader 可以配合法线贴图一起用 适用于平面物体 Mirror-AlphaBumpSpec.shader 实时镜面发射、透明材质,可以同时反射和透明效果,也可以配合法线贴图,适用于平面物体 Mirror-AlphaSpecSphere.shader 与上面材质相同,适用于球面物体,不能使用法线贴图 使用很简单,就几个参数,具体效果要慢慢调节,简单解说几个关键参数: Main Material Blend Level:主材质的混合浓度 Bump Rate:法线贴图强度 Reflection Rate 反射强度 Reflective Color 反射颜色 Reflective Distortion 反射图受法线影响强度 Transparency 同时透明、反射材质,调节透明反射混合的比例 ,0是全反射 1是全透明 Distortion 反射、透明受法线影响的强度 另外每个shader都有个自动的贴图是不需要设置的,由脚本自动设置 Mirror脚本参数: Disable Pixel Lights 禁用Pixel Lights,对应unity摄像机的这个设置 Texture Size 反射贴图精度 缺省是256 如果觉得反射很模糊直接把这个加大就行了 即时生效 所以不要设太大了,1024足以应付绝大多数要求了。 Is Flat Mirror:如果是平面反射物体就勾上,球体点掉,材质也要选择相应的 Reflect Layer 反射的culling mask,可以屏蔽掉指定的层 shader和脚本都是参考unity的water效果,脚本基本就是water包里反射脚本的简化版 由于只是模拟,并不是真正的光线跟踪效果,所以折射效果并不准确,但是基本能满足观感。 注意:目前只适用于forward 渲染,Deferred下会有贴图倒置、光线暗淡的问题 尽量避免反射物体互相反射,消耗巨大而且效果不准确 实时反射本身也开销极大,尽量不要滥用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农老K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值