在Unity的Shader Graph可视化着色器编辑器中,Sawtooth Wave节点是一个功能强大的数学工具节点,它能够根据输入值生成锯齿波形。锯齿波是一种常见的基本波形,在图形编程和着色器开发中有着广泛的应用。这个节点通过数学运算将输入值转换为具有线性上升和突然下降特征的波形输出,为着色器效果提供了丰富的动态可能性。
锯齿波在图形学中的应用可以追溯到早期的计算机图形和音频合成领域。它的名称来源于其波形形状类似于锯齿的剖面 - 从最低点线性上升到最高点,然后瞬间回落到最低点,如此循环往复。这种独特的波形特性使其特别适合创建循环动画、纹理变换、时间相关效果以及其他需要周期性变化的各种视觉效果。
在Shader Graph的节点库中,Sawtooth Wave节点属于数学类别下的高级数学函数节点。与正弦波、三角波和方波等其他波形节点一样,它提供了一种在着色器中生成周期性变化的便捷方法,而无需编写复杂的数学代码。通过简单的节点连接,开发者就能利用锯齿波的特性创造出各种引人注目的视觉效果。
理解Sawtooth Wave节点的工作原理和应用场景,对于掌握Shader Graph的高级功能和创建复杂的着色器效果至关重要。本篇文章将深入探讨该节点的各个方面,包括其数学原理、参数设置、实际应用示例以及优化技巧,帮助读者全面掌握这一强大工具的使用方法。
描述
Sawtooth Wave节点的核心功能是根据输入的数值生成锯齿波形。从数学角度看,锯齿波是一种分段线性周期函数,其特点是在每个周期内从最小值线性增加到最大值,然后在周期结束时瞬间跳回最小值,形成一个类似锯齿的形状。
在Shader Graph中,Sawtooth Wave节点接受一个输入值,并返回对应的锯齿波输出。这个输入值可以是标量(单个浮点数),也可以是矢量(如float2、float3或float4)。当输入是矢量时,节点会对每个分量独立计算锯齿波,这使得它可以同时处理多个维度的数据,大大提高了使用的灵活性。
锯齿波的数学表达式可以表示为:f(x) = 2 * (x - floor(0.5 + x))。这个公式确保了输出值在-1到1的范围内周期性变化。具体来说,当输入值从0增加到1时,输出值从-1线性增加到1;当输入值达到1时,输出瞬间跳回-1,然后开始下一个周期。这种特性使得锯齿波非常适合用于创建循环动画和周期性效果。
与Shader Graph中的其他波形节点相比,Sawtooth Wave节点具有独特的特性。例如,正弦波(Sine节点)产生平滑的周期性变化,三角波(Triangle Wave节点)产生线性上升和下降的波形,而方波(Square Wave节点)则在两个固定值之间瞬时切换。锯齿波的线性上升和瞬时下降特性使其在创建扫描效果、进度指示器和时间相关的变换方面具有独特优势。
在实际应用中,Sawtooth Wave节点通常与Time节点结合使用,以创建基于时间的动画效果。通过将时间值作为输入,可以生成随时间周期性变化的锯齿波,进而驱动各种视觉属性的变化。这种组合是创建动态着色器效果的常用技术。
端口

Sawtooth Wave节点的端口系统设计简洁而强大,允许用户灵活地连接各种类型的输入数据,并获取相应的输出结果。理解每个端口的功能和特性对于有效使用该节点至关重要。
输入端口
- 名称:In
- 方向:输入
- 类型:动态矢量
- 绑定:无
- 描述:输入值是锯齿波函数的参数,决定了输出波形的位置。这个端口接受动态矢量类型,意味着它可以连接浮点数、二维向量、三维向量或四维向量。当输入是矢量时,节点会对每个分量独立计算锯齿波,返回相同维度的矢量输出。这种设计使得节点能够同时处理多个通道的数据,例如分别处理颜色的R、G、B通道或纹理坐标的U、V通道。
输入端口的行为特性值得特别注意。由于锯齿波是周期函数,输入值的范围会影响输出结果。对于任何实数输入x,输出f(x)始终满足-1 ≤ f(x) ≤ 1。当输入值均匀增加时,输出值会线性地从-1增加到1,然后在每个整数点瞬间跳回-1。这种特性使得输入值可以代表时间、位置或其他任何需要周期性变化的参数。
输出端口
- 名称:Out
- 方向:输出
- 类型:动态矢量
- 绑定:无
- 描述:输出值是输入值对应的锯齿波计算结果。输出类型与输入类型保持一致 - 如果输入是浮点数,输出也是浮点数;如果输入是float4,输出也是float4。输出的每个分量都是对应输入分量的锯齿波值,范围在-1到1之间。
输出端口的数值特性对于实际应用非常重要。由于输出范围固定在-1到1,用户通常需要对其进行缩放和偏移,以适配具体的应用场景。例如,要将输出范围转换为0到1,可以使用公式(Out + 1) * 0.5;要转换为其他任意范围a,b,可以使用公式a + (Out + 1) * (b - a) * 0.5。这种灵活性使得Sawtooth Wave节点可以适应各种不同的应用需求。
端口连接示例
在实际使用中,Sawtooth Wave节点的端口可以连接到Shader Graph中的各种其他节点。以下是一些常见的连接示例:
- 将Time节点连接到In端口,可以创建基于时间的锯齿波动画
- 将Position节点连接到In端口,可以创建基于空间位置的锯齿波模式
- 将Texture Coordinates节点连接到In端口,可以创建依赖于UV坐标的波形纹理
- 将Out端口连接到颜色属性,可以创建周期性变化的颜色效果
- 将Out端口连接到Alpha属性,可以创建闪烁或淡入淡出效果
- 将Out端口连接到变换属性(如平移、旋转、缩放),可以创建周期性动画
通过灵活地组合这些连接,开发者可以创造出各种复杂的动态视觉效果,而无需编写复杂的着色器代码。
生成的代码示例
当在Shader Graph中使用Sawtooth Wave节点时,Unity会在背后生成相应的HLSL代码来实现锯齿波功能。理解这些生成的代码有助于深入掌握节点的内部工作原理,并在需要时进行自定义修改或优化。
以下是Sawtooth Wave节点生成的典型代码示例:
sql
void Unity_SawtoothWave_float4(float4 In, out float4 Out)
{
Out = 2 * (In - floor(0.5 + In));
}
这段代码定义了一个名为Unity_SawtoothWave_float4的函数,它接受一个float4类型的输入参数In,并通过输出参数Out返回计算结果。函数内部的数学表达式是锯齿波的核心实现。
代码分析
让我们逐部分分析这段生成的代码:
- 函数签名 :
void Unity_SawtoothWave_float4(float4 In, out float4 Out)定义了一个返回void类型的函数,它接受一个输入参数In和一个输出参数Out。使用out关键字表示Out参数是通过引用传递的,函数内部对其的修改会影响外部变量。 - 数学表达式 :
Out = 2 * (In - floor(0.5 + In))是锯齿波的数学实现。这个表达式可以分解为几个步骤理解:- 首先计算
0.5 + In,将输入值偏移0.5 - 然后应用
floor函数,向下取整到最接近的整数 - 接着用原始输入值In减去这个取整结果,得到小数部分减去0.5的效果
- 最后乘以2,将范围从-0.5, 0.5扩展到-1, 1
- 首先计算
- 分量处理:由于输入参数In是float4类型,所有的数学运算都会自动应用于每个分量(x、y、z、w)。这意味着对于矢量输入,函数会并行计算四个独立的锯齿波,每个分量一个。
数学原理
锯齿波函数的数学原理基于取模运算的概念,但通过floor函数实现。标准的锯齿波函数通常定义为f(x) = x - floor(x),这会生成从0到1的锯齿波。而Shader Graph中的实现f(x) = 2 * (x - floor(0.5 + x))则生成了从-1到1的锯齿波。
这种实现的优势在于输出范围是对称的(-1到1),这在图形编程中通常更加实用。对称范围使得波形既可用于正方向的变化,也可用于负方向的变化,提供了更大的灵活性。
变体函数
根据输入数据类型的不同,Shader Graph会生成不同版本的锯齿波函数:
arduino
// 处理float类型输入
void Unity_SawtoothWave_float(float In, out float Out)
{
Out = 2 * (In - floor(0.5 + In));
}
// 处理float2类型输入
void Unity_SawtoothWave_float2(float2 In, out float2 Out)
{
Out = 2 * (In - floor(0.5 + In));
}
// 处理float3类型输入
void Unity_SawtoothWave_float3(float3 In, out float3 Out)
{
Out = 2 * (In - floor(0.5 + In));
}
这些变体函数的内部逻辑完全相同,只是处理的数据类型不同。Shader Graph会根据实际连接的输入类型自动选择适当的函数版本。
自定义修改
了解生成的代码后,高级用户可以根据需要自定义锯齿波的行为。例如,可以修改函数以改变波形的特性:
csharp
// 自定义锯齿波函数,可调整斜率和周期
void CustomSawtoothWave(float In, float Slope, float Period, out float Out)
{
float normalized = frac(In / Period); // 归一化到[0,1]范围
Out = -1 + 2 * Slope * normalized; // 应用斜率参数
}
这种自定义扩展提供了更大的灵活性,允许开发者创建更特殊的波形效果,满足特定的视觉需求。
使用示例
Sawtooth Wave节点在Shader Graph中有广泛的应用场景。通过不同的连接方式和参数设置,可以创造出各种有趣的视觉效果。以下是一些具体的使用示例,展示了该节点的多功能性和实用性。
基础锯齿波生成
最基本的应用是生成一个简单的锯齿波,用于驱动各种属性的周期性变化。
- 创建一个新的Unlit Shader Graph
- 添加Time节点,获取着色器运行时间
- 添加Sawtooth Wave节点,将Time节点的输出连接到其In端口
- 将Sawtooth Wave节点的Out端口连接到Base Color端口
- 观察结果:材质的颜色会随时间从黑色线性变化到白色,然后瞬间跳回黑色,循环往复
这个简单的示例演示了锯齿波的基本行为。通过调整Time节点的输出(例如乘以一个系数改变频率),可以控制颜色变化的速率。
扫描线效果
利用锯齿波可以创建经典的扫描线效果,类似于雷达屏幕或老式显示器的视觉效果。
- 创建UV坐标节点,获取纹理坐标
- 添加Time节点,获取时间值
- 使用Sawtooth Wave节点处理时间值,生成锯齿波
- 将锯齿波输出与UV的Y坐标相加,创建垂直移动的扫描线
- 使用Step或SmoothStep函数将扫描线转换为清晰的边界
- 将结果与基础颜色混合,创建扫描线效果
通过调整锯齿波的频率和扫描线的宽度,可以创建不同风格的扫描效果。这种方法也可以用于创建水平扫描线或对角线扫描线。
脉冲发光效果
锯齿波非常适合创建周期性发光效果,如警示灯或能量核心的脉冲。
- 使用Time节点驱动Sawtooth Wave节点,生成基础波形
- 通过Remap节点将波形范围从-1,1转换为0,1
- 将转换后的波形输入到Emission端口,控制自发光强度
- 为了增强效果,可以将波形值乘以一个系数或应用幂函数增加对比度
- 可选:添加颜色渐变,根据强度值变化发光颜色
这种技术可以创建出从完全无光到最强发光的平滑过渡,然后突然重置的视觉效果,非常适合用于科幻场景中的各种能量效果。
旋转动画
锯齿波可以驱动对象的旋转,创建连续的旋转动画。
- 添加Time节点获取时间
- 使用Sawtooth Wave节点处理时间,生成锯齿波
- 将波形范围从-1,1重新映射到0,360(度数)或0,2π(弧度)
- 将结果连接到Rotation变换节点
- 应用至对象,观察连续旋转效果
与其他波形不同,锯齿波驱动的旋转会匀速旋转然后瞬间重置,创造出独特的视觉效果。通过调整锯齿波的频率,可以控制旋转速度。
进度指示器
利用锯齿波的线性特性,可以创建各种进度指示器效果。
- 使用Time节点驱动Sawtooth Wave节点
- 通过Remap节点将输出范围从-1,1转换为0,1
- 使用Step或SmoothStep函数创建进度条遮罩
- 将遮罩应用于UI元素或场景中的几何体
- 调整锯齿波频率控制进度条填充速度
这种方法可以创建循环进度指示器,常用于加载界面或技能冷却效果。
多通道波形应用
利用Sawtooth Wave节点对矢量输入的支持,可以同时处理多个通道,创建复杂的多维度效果。
- 创建float4类型的输入,例如组合时间、位置或其他参数
- 将float4输入连接到Sawtooth Wave节点
- 节点会输出float4结果,每个分量对应一个独立的锯齿波
- 将这些分量分别用于控制不同的材质属性,如颜色、透明度、反射强度等
- 通过为每个分量设置不同的偏移或频率,可以创建出丰富的动态效果
这种技术的优势在于只需一个节点就能生成多个相关的波形,提高了着色器的效率和可读性。
结合其他波形
Sawtooth Wave节点可以与其他波形节点结合使用,创建更复杂的复合波形。
- 分别创建Sawtooth Wave、Sine Wave和Triangle Wave节点
- 使用相同的Time输入驱动所有这些节点
- 通过加法、乘法或混合节点组合不同的波形
- 将复合波形用于驱动材质属性或变换
- 调整各种波形的权重和相位,创造出独特的动态模式
这种波形合成技术源自音频合成领域,在视觉特效中同样有效,可以生成极其丰富和有机的动画效果。
参数与配置
虽然Sawtooth Wave节点本身没有直接的参数可以调整,但通过与其他节点组合,可以实现对波形各种特性的控制。理解这些间接参数和配置方法对于充分利用该节点至关重要。
频率控制
锯齿波的频率决定了波形完成一个完整周期所需的时间。在Shader Graph中,可以通过数学运算调整输入值来控制频率。
- 高频波形 :将Time节点输出乘以大于1的系数,例如:
Time * 5,这会创建快速的锯齿波变化 - 低频波形 :将Time节点输出乘以小于1的系数,例如:
Time * 0.2,这会创建缓慢的锯齿波变化 - 精确频率控制 :使用公式
Time * 2 * PI * desiredFrequency,可以精确控制波形频率(单位:赫兹)
频率控制是调整锯齿波行为最基本也是最重要的方法,它直接影响基于波形的动画速度。
相位偏移
相位偏移允许调整波形的起始点,在创建多个相关但不同步的波形时特别有用。
- 基础相位偏移 :在输入值上加上一个常数,例如:
Time + 0.3,这会将波形向左或向右移动 - 相对相位偏移:当创建多个波形时,为每个波形设置不同的相位偏移,可以创建交错或互补的效果
- 动态相位偏移:使用另一个波形或时间函数控制相位偏移,可以创建 evolving 的波形模式
相位偏移技术常用于创建复杂的多层级动画,其中各个部分以协调但不同步的方式运动。
振幅与偏置
Sawtooth Wave节点的输出范围固定为-1,1,但通过后续处理可以调整波形的振幅和偏置。
- 振幅调整 :将波形输出乘以一个系数,例如:
Sawtooth * 0.5,这会将范围缩小到-0.5,0.5 - 偏置调整 :在波形输出上加上一个常数,例如:
Sawtooth + 1,这会将范围移动到0,2 - 范围重映射 :结合乘法和加法,可以将波形映射到任意范围,例如:
Sawtooth * 0.5 + 0.5将范围转换为0,1
振幅和偏置调整使得锯齿波可以适应各种不同的应用场景,无论需要的是对称变化还是单向变化。
波形变形
通过数学运算,可以改变锯齿波的基本形状,创建变体波形。
- 绝对值锯齿波:对锯齿波取绝对值,可以创建V形波形,从0上升到1然后下降到0
- 反向锯齿波:将锯齿波乘以-1,可以创建从1下降到-1的波形
- 平滑过渡:在波形跳变点附近应用平滑函数,可以创建圆角锯齿波,避免突然跳变
- 非线性变换:对锯齿波应用幂函数或指数函数,可以创建加速或减速的波形
波形变形技术扩展了锯齿波的应用范围,使其能够模拟更多种类的自然现象和艺术效果。
矢量输入处理
当Sawtooth Wave节点接收矢量输入时,可以通过分量操作实现更精细的控制。
- 统一处理:直接将矢量输入连接到节点,所有分量使用相同的波形函数
- 分量缩放:在连接前对矢量的各个分量应用不同的缩放系数,创建不同频率的波形
- 分量偏移:为矢量的各个分量设置不同的相位偏移,创建错开的波形
- 选择性处理:使用Swizzle节点只将矢量的特定分量连接到波形节点,其他分量保持不变
矢量输入处理使得单个Sawtooth Wave节点可以同时控制多个相关但不同的动画参数,提高了着色器的效率和一致性。
优化与性能
在着色器开发中,性能优化是一个重要考虑因素。虽然Sawtooth Wave节点本身计算开销不大,但在复杂场景或移动平台上的使用仍需注意性能影响。
计算复杂度分析
Sawtooth Wave节点的计算相对简单,主要包含以下操作:
- 一次加法:
0.5 + In - 一次floor函数调用
- 一次减法:
In - floorResult - 一次乘法:
2 * difference
【Unity Shader Graph 使用与特效实现】专栏-直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)