【节点】[Refract节点]原理解析与实际应用

【Unity Shader Graph 使用与特效实现】专栏-直达

在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节点在后台生成的代码展示了其内部实现逻辑。以下代码示例展示了两种模式下可能的实现方式:

ini 复制代码
// 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 使用与特效实现】专栏-直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

相关推荐
SmalBox1 天前
【节点】[Reflection节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox2 天前
【节点】[Projection节点]原理解析与实际应用
unity3d·游戏开发·图形学
qiqizizzz2 天前
Unity编辑器配置问题 #01 | 内部打开Rider失败
unity3d
SmalBox3 天前
【节点】[Distance节点]原理解析与实际应用
unity3d·游戏开发·图形学
winlife_4 天前
把 Godot 编辑器接入 AI:Funplay MCP for Godot 介绍
人工智能·编辑器·godot·ai编程·游戏开发·mcp
SmalBox4 天前
【节点】[Tangent节点]原理解析与实际应用
unity3d·游戏开发·图形学
winlife_4 天前
把 Cocos Creator 编辑器接入 AI:Funplay MCP for Cocos 介绍
人工智能·编辑器·ai编程·cocos creator·游戏开发·claude·mcp
SmalBox5 天前
【节点】[RadiansToDegrees节点]原理解析与实际应用
unity3d·游戏开发·图形学
音视频牛哥6 天前
大牛直播SDK(SmartMediaKit)Android平台Unity3D RTSP/RTMP播放器集成实践
android·unity3d·rtsp播放器·rtmp播放器·unity3d rtmp播放器·安卓unity rtsp播放器·安卓unity rtmp播放器