【节点】[Refract节点]原理解析与实际应用
在Unity URP Shader Graph中,Refract节点是一个功能强大的工具,用于模拟光线在不同介质之间传播时发生的折射现象。折射是光学中的基本物理现象,当光线从一种介质进入另一种密度不同的介质时,其传播方向会发生改变。这种效果在现实世界中随处可见,比如水中的物体看起来位置偏移,玻璃透镜对光线的聚焦作用,或者热空气上方的景象产生扭曲等。
Refract节点通过精确的物理计算来重现这些效果,为游戏和实时渲染应用增添了重要的视觉真实感。该节点基于斯涅尔定律(Snell's Law)的原理实现,这是描述光线折射行为的基本物理定律。斯涅尔定律表明,入射角的正弦值与折射角的正弦值之比等于两种介质的折射率之比。
在折射计算中,存在一个重要的物理概念——全内反射角。当光线从高折射率介质进入低折射率介质时,如果入射角大于某个特定角度(临界角),光线将不会发生折射,而是完全被反射回原介质。这种现象称为全内反射,光纤通信就是基于这一原理工作的。
为了避免在全内反射情况下产生无效的数学结果(NaN),Refract节点提供了两种工作模式:Safe模式和CriticalAngle模式。Safe模式会在达到临界角时返回一个空向量,确保计算的稳定性;而CriticalAngle模式则会严格遵循物理定律,可能在临界条件下产生NaN结果。在大多数实际应用中,推荐使用Safe模式以保证着色器的稳定性。
端口
Refract节点包含多个输入和输出端口,每个端口都有特定的功能和用途:
| 名称 | 方向 | 类型 | 绑定 | 描述 |
|---|---|---|---|---|
| Incident | 输入 | Vector | 无 | 从光源到表面的标准化向量。这个向量表示入射光线的方向,必须是单位向量。在实际应用中,这可以是从光源到像素的向量,或者从摄像机到表面的向量,取决于具体的渲染需求。 |
| Normal | 输入 | Vector | 无 | 引起折射的表面的标准化法向量。法向量定义了表面的朝向,对折射方向的计算至关重要。必须确保输入的法向量是单位向量,否则会导致不准确的折射效果。 |
| IOR Source | 输入 | Float | 无 | 光源所处介质的折射率。折射率是描述介质对光线偏折能力的物理量,真空的折射率为1.0,空气约为1.0003,水约为1.33,玻璃约为1.5-1.9。 |
| IOR Medium | 输入 | Float | 无 | 光线折射进入的介质的折射率。这个值决定了光线进入新介质后的偏折程度。 |
| Refracted | 输出 | Vector | 无 | 折射后的向量。这是计算得到的折射光线方向,可以用于后续的着色计算,如采样环境贴图或计算光照。 |
| Intensity | 输出 | Float | 无 | 折射的强度。这个输出值表示折射效果的强度,可以用于混合折射效果与其他效果,或者控制折射的可见度。 |
输入端口详解
Incident向量是折射计算的起点,它定义了光线的初始方向。在实时渲染中,这个向量通常是从摄像机位置指向表面点的方向向量,或者是来自光源的方向向量。确保这个向量是标准化(单位长度)的非常重要,因为非标准化向量会导致不准确的折射计算。
Normal向量代表了表面的法线方向,它决定了折射发生的平面。在Shader Graph中,法线信息通常来自模型的顶点法线、法线贴图,或者是通过其他节点计算得到的自定义法线。与Incident向量一样,Normal向量也必须是标准化的。
IOR Source和IOR Medium两个参数共同决定了折射的强度。折射率比值(IOR Source / IOR Medium)越大,光线的偏折程度就越大。当光线从低折射率介质进入高折射率介质时(如从空气进入水),折射角会小于入射角;反之,当光线从高折射率介质进入低折射率介质时,折射角会大于入射角。
输出端口详解
Refracted输出端口提供了计算得到的折射方向向量。这个向量可以用于多种用途,最常见的是用于采样环境贴图(如Cubemap)来模拟透明材质的折射效果,或者用于光线追踪计算。
Intensity输出端口提供了折射效果的强度值,这个值基于菲涅尔效应和临界角计算得到。当入射角接近临界角时,折射强度会发生变化,这个输出可以帮助开发者创建更加物理准确的折射效果。
控制
Refract节点提供了一个重要的控制参数,用于管理全内反射情况下的处理方式:
| 名称 | 类型 | 选项 | 描述 |
|---|---|---|---|
| Mode | 下拉菜单 | Safe、CriticalAngle | • Safe:在达到临界角时返回空向量结果,以避免NaN结果。这种模式确保了计算的稳定性,适合大多数实时渲染应用。• CriticalAngle:忽略Safe检查,严格遵循物理定律,可能在达到临界角时产生NaN结果。这种模式适合需要完全物理准确性的离线渲染或学术研究。 |
Mode控制详解
Safe模式是推荐的工作模式,特别是在实时渲染应用中。当入射角达到或超过临界角时,Safe模式会返回一个零向量,避免了数学上的不确定结果。这种处理方式虽然不完全符合物理定律,但在视觉上通常是可接受的,并且保证了着色器的稳定性。
CriticalAngle模式则严格遵循物理计算,不会对临界情况进行特殊处理。这种模式在入射角超过临界角时会产生无效的数学结果(NaN),这可能导致渲染错误或性能问题。只有在特定情况下,如学术研究或需要完全物理准确性的应用中,才建议使用此模式。
选择哪种模式取决于具体的应用需求。对于游戏和实时可视化应用,Safe模式通常是更好的选择,因为它提供了稳定的性能和可接受的外观效果。对于科学模拟或高质量的离线渲染,CriticalAngle模式可能更合适,但需要额外的错误处理机制。
生成的代码示例
Refract节点在后台生成的代码展示了其内部实现逻辑。以下代码示例展示了两种模式下可能的实现方式:
// CriticalAngle模式的实现
void Unity_RefractCriticalAngle(float3 Incident, float3 Normal, float IORInput, float IORMedium, out float Out)
{
$precision internalIORInput = max(IORInput, 1.0);
$precision internalIORMedium = max(IORMedium, 1.0);
$precision eta = internalIORInput/internalIORMedium;
$precision cos0 = dot(Incident, Normal);
$precision k = 1.0 - eta*eta*(1.0 - cos0*cos0);
Refracted = k >= 0.0 ? eta*Incident - (eta*cos0 + sqrt(k))*Normal : reflect(Incident, Normal);
Intensity = internalIORSource <= internalIORMedium ?
saturate(F_Transm_Schlick(IorToFresnel0(internalIORMedium, internalIORSource), -cos0)) :
(k >= 0.0 ? saturate(F_FresnelDielectric(internalIORMedium/internalIORSource, -cos0)) : 0.0);
}
// Safe模式的实现
void Unity_RefractSafe(float3 Incident, float3 Normal, float IORInput, float IORMedium, out float Out)
{
$precision internalIORInput = max(IORInput, 1.0);
$precision internalIORMedium = max(IORMedium, 1.0);
$precision eta = internalIORInput/internalIORMedium;
$precision cos0 = dot(Incident, Normal);
$precision k = 1.0 - eta*eta*(1.0 - cos0*cos0);
Refracted = eta*Incident - (eta*cos0 + sqrt(max(k, 0.0)))*Normal;
Intensity = internalIORSource <= internalIORMedium ?
saturate(F_Transm_Schlick(IorToFresnel0(internalIORMedium, internalIORSource), -cos0)) :
(k >= 0.0 ? saturate(F_FresnelDielectric(internalIORMedium/internalIORSource, -cos0)) : 1.0);
}
代码解析
在CriticalAngle模式的实现中,代码首先确保折射率不小于1.0,然后计算两种介质的折射率比值(eta)。接着计算入射角余弦值(cos0)和判别式k,这个判别式决定了是否会发生全内反射。
当k >= 0时,表示折射是可能的,代码会计算标准的折射向量;当k < 0时,表示发生全内反射,代码会调用reflect函数计算反射向量。
折射强度的计算考虑了菲涅尔效应,使用Schlick近似或精确的菲涅尔公式,具体取决于折射率的相对大小。
在Safe模式的实现中,主要的区别在于对k值的处理。通过使用max(k, 0.0)确保平方根参数不会为负,从而避免了NaN结果。在强度计算中,当k < 0时返回固定值1.0,而不是0.0,这有助于创建更平滑的视觉效果。
实际应用考虑
在实际使用Refract节点时,有几个重要的考虑因素:
- 向量标准化:确保输入的Incident和Normal向量都是单位长度的,否则会导致不准确的折射效果。
- 折射率选择:选择合适的折射率值对实现逼真的效果至关重要。可以参考真实材料的折射率值,如水1.33、玻璃1.5-1.9、钻石2.42等。
- 性能优化:折射计算相对复杂,特别是在移动设备上使用时,应注意性能影响。可以考虑使用简化模型或仅在必要时启用折射效果。
- 与其他效果的结合:折射效果通常需要与反射、透明度和光照计算结合使用,才能创建出完整的材质外观。
【Unity Shader Graph 使用与特效实现】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

在Unity URP Shader Graph中,Refract节点是一个功能强大的工具,用于模拟光线在不同介质之间传播时发生的折射现象。折射是光学中的基本物理现象,当光线从一种介质进入另一种密度不同
浙公网安备 33010602011771号