Sphere Mask 节点是 Unity Shader Graph 中一个功能强大的工具节点,用于创建基于球体形状的遮罩效果。该节点通过计算输入坐标与指定中心点之间的距离,生成一个球形的渐变遮罩,广泛应用于各种着色器效果中,包括高光、发光、溶解、过渡等视觉效果。
在实时渲染中,球形遮罩是一种基础但极其有用的技术。它能够模拟光线衰减、创建局部特效、实现空间混合等多种效果。Sphere Mask 节点的设计使得开发者无需编写复杂的数学公式即可实现这些功能,大大提高了着色器开发的效率。
描述
Sphere Mask 节点的核心功能是创建一个源自输入 Center 的球体遮罩。这个球体遮罩是通过计算输入坐标与中心点之间的 Distance 来实现的,并使用 Radius 和 Hardness 参数进行精细调整。
数学原理
从技术角度来看,Sphere Mask 节点基于以下数学公式:
scss
mask = 1 - saturate((distance(Coords, Center) - Radius) / (1 - Hardness))
这个公式可以分解为几个关键步骤:
- 首先计算输入坐标与中心点之间的欧几里得距离
- 然后减去指定的半径值,得到距离球体表面的偏移量
- 接着通过硬度参数对结果进行归一化和软化处理
- 最后使用 saturate 函数将结果限制在 0,1 范围内
空间适用性
Sphere Mask 节点的一个显著特点是其空间适用性广泛:
- 它完全适用于 2D 和 3D 空间
- 基于 Coords 输入中的矢量坐标工作
- 这些坐标可以是 3D 空间坐标(如世界空间位置、物体空间位置)
- 也可以是 2D 坐标(如 UV 坐标、屏幕空间坐标)
这种灵活性使得 Sphere Mask 节点可以应用于各种不同的渲染场景,从简单的纹理混合到复杂的世界空间特效。
硬度参数的特殊行为
Hardness 参数的行为需要特别注意:
- 当 Hardness = 0 时,遮罩边缘完全硬化,产生锐利的边界
- 当 Hardness = 1 时,遮罩边缘完全软化,产生平滑的渐变过渡
- 在实际使用中,Hardness 应避免设置为精确的 1.0,因为这会导致除以零的错误
- 通常建议使用接近但不等于 1 的值,如 0.99
端口

Sphere Mask 节点包含多个输入和输出端口,每个端口都有特定的功能和数据类型要求。深入了解这些端口的特性对于正确使用该节点至关重要。
输入端口
- Coords 端口
- 方向:输入
- 类型:动态矢量(Dynamic Vector)
- 绑定:无
- 描述:这是球体遮罩计算的坐标空间输入。该端口接受 2D、3D 或 4D 矢量,但通常使用 2D 或 3D 矢量。坐标的类型决定了遮罩应用的空间:
- 使用世界空间位置时,遮罩在 3D 空间中固定
- 使用 UV 坐标时,遮罩随纹理坐标移动
- 使用物体空间位置时,遮罩随物体移动而移动
- 使用技巧:根据需要的效果选择合适的坐标空间。例如,创建世界空间发光效果应使用世界位置,而创建材质图案应使用 UV 坐标。
- Center 端口
- 方向:输入
- 类型:动态矢量(Dynamic Vector)
- 绑定:无
- 描述:定义球体原点的坐标。此端口的维度应与 Coords 端口匹配:
- 如果 Coords 是 2D 矢量,Center 也应是 2D 矢量
- 如果 Coords 是 3D 矢量,Center 也应是 3D 矢量
- 使用技巧:Center 可以是固定值,也可以是动态计算的。例如,可以将其连接到脚本提供的参数,实现动态移动的遮罩效果。
- Radius 端口
- 方向:输入
- 类型:Float(浮点数)
- 绑定:无
- 描述:定义球体的半径大小。此参数决定了遮罩影响的范围:
- 较小的值产生小范围的遮罩效果
- 较大的值产生大范围的遮罩效果
- 使用技巧:Radius 可以动画化,创建膨胀或收缩的效果。结合其他节点,可以实现基于距离的自动半径调整。
- Hardness 端口
- 方向:输入
- 类型:Float(浮点数)
- 绑定:无
- 描述:控制球体边缘的软化程度或衰减强度:
- 值为 0 时产生硬边缘,遮罩在半径处突然变化
- 值接近 1 时产生软边缘,遮罩从中心到边缘平滑过渡
- 重要限制:技术上应避免设置为精确的 1.0,建议使用 0.99 作为最大值
- 使用技巧:通过动画化 Hardness 值,可以创建边缘逐渐硬化或软化的动态效果。
输出端口
- Out 端口
- 方向:输出
- 类型:动态矢量(Dynamic Vector)
- 绑定:无
- 描述:输出遮罩值,范围在 0,1 之间:
- 值为 1 表示完全在球体内(或非常接近中心)
- 值为 0 表示完全在球体外(远离中心超过半径加软化区域)
- 中间值表示在过渡区域内的位置
- 输出特性:输出值的维度与输入 Coords 的维度相同,但通常只使用其标量值
- 使用技巧:输出可以连接到各种材质属性,如透明度、发射强度、颜色混合因子等
端口连接最佳实践
为了获得最佳效果,建议遵循以下端口连接准则:
- 确保 Coords 和 Center 端口的维度匹配
- 为 Hardness 参数设置合理的范围,避免极端值
- 使用 Clamp 节点限制 Radius 和 Hardness 的取值范围
- 当需要动态效果时,使用 Time 节点或脚本参数驱动 Center 和 Radius
生成的代码示例
理解 Sphere Mask 节点生成的代码对于高级着色器编程和调试非常有帮助。以下是对生成代码的详细分析。
核心函数实现
csharp
void Unity_SphereMask_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out)
{
Out = 1 - saturate((distance(Coords, Center) - Radius) / (1 - Hardness));
}
代码分析
这个函数实现了 Sphere Mask 节点的核心功能:
- 函数签名 :使用
float4类型处理四维向量,但实际使用时通常只用到二维或三维分量 - 距离计算 :
distance(Coords, Center)计算输入坐标与中心点之间的欧几里得距离 - 半径调整 :
distance(Coords, Center) - Radius将距离偏移半径值,使结果在球体表面为零 - 硬度处理 :
/ (1 - Hardness)根据硬度参数调整衰减的陡峭程度 - 范围限制 :
saturate(...)确保结果在 0,1 范围内,防止无效值 - 最终反转 :
1 - ...反转结果,使中心值为 1,边缘值为 0
数学推导
从数学角度理解这个公式:
设:
- d = distance(Coords, Center) // 坐标到中心的距离
- r = Radius // 球体半径
- h = Hardness // 硬度参数
则公式可写为:
mask = 1 - saturate((d - r) / (1 - h))
分析不同情况:
- 当 d ≤ r 时:(d - r) ≤ 0,saturate 结果为 0,mask = 1
- 当 d ≥ r + (1 - h) 时:(d - r) ≥ (1 - h),saturate 结果为 1,mask = 0
- 当 r < d < r + (1 - h) 时:mask 在 1 和 0 之间线性过渡
自定义变体
了解核心算法后,可以创建自定义的 Sphere Mask 变体:
scss
// 反向球体遮罩(中心为0,边缘为1)
void Unity_ReverseSphereMask_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out)
{
Out = saturate((distance(Coords, Center) - Radius) / (1 - Hardness));
}
// 带最大范围的球体遮罩
void Unity_SphereMaskRange_float4(float4 Coords, float4 Center, float MinRadius, float MaxRadius, float Hardness, out float4 Out)
{
float dist = distance(Coords, Center);
Out = 1 - saturate((dist - MinRadius) / (MaxRadius - MinRadius));
Out *= saturate((MaxRadius - dist) / (1 - Hardness));
}
// 使用不同距离度量的球体遮罩
void Unity_SphereMaskChebyshev_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out)
{
float4 diff = abs(Coords - Center);
float dist = max(diff.x, max(diff.y, diff.z));
Out = 1 - saturate((dist - Radius) / (1 - Hardness));
}
性能考虑
在性能敏感的场景中,可以考虑以下优化:
ini
// 优化版本:避免除法操作
void Unity_SphereMaskOptimized_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out)
{
float dist = distance(Coords, Center);
float invHardness = 1.0 / (1.0 - Hardness);
Out = 1 - saturate((dist - Radius) * invHardness);
}
// 近似版本:使用平方距离避免开方运算
void Unity_SphereMaskApprox_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out)
{
float4 diff = Coords - Center;
float sqDist = dot(diff, diff);
float sqRadius = Radius * Radius;
Out = 1 - saturate((sqrt(sqDist) - Radius) / (1 - Hardness));
}
调试技巧
当 Sphere Mask 效果不符合预期时,可以使用以下调试版本:
csharp
// 调试版本:输出中间计算值
void Unity_SphereMaskDebug_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out, out float RawDistance, out float AdjustedDistance)
{
RawDistance = distance(Coords, Center);
AdjustedDistance = (RawDistance - Radius) / (1 - Hardness);
Out = 1 - saturate(AdjustedDistance);
}
【Unity Shader Graph 使用与特效实现】专栏-直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)