【动态着色】Unity 实现箭头图案

33 阅读9分钟

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

箭头图案效果的核心原理与数学基础

箭头的视觉本质与空间映射

箭头图案在 Shader Graph 中的实现核心是利用 参数化曲线路径 控制顶点偏移,结合法线扰动和颜色混合,创造出方向感强烈的箭头纹理。其核心数学逻辑围绕以下两点展开:

  • 路径参数化:通过一维参数(t)控制二维坐标(x,y),使用贝塞尔曲线或二次曲线公式定义箭头的形状轮廓,P(t) = (3(1-t)^2*t + 2(1-t)*t^2) 定义平滑的箭头主体。
  • 方向向量映射:利用归一化的方向向量与法线计算,通过 dot(normal, direction) 判断表面朝向,实现箭头的方向性高亮和阴影效果。

关键数学特性

  • 分段函数建模:将箭头分为箭头尖端、箭头杆身、箭头尾部三段,分别使用不同的坐标映射公式:
    • 尖端:x = cos(θ*t), y = sin(θ*t)(极坐标参数化)
    • 杆身:线性插值 P(t) = P_start + t*(P_end - P_start)
  • 法线扰动:通过 sin(n.x * freq + time * speed) 在箭头表面添加流动纹理,增强科技感。
  • 宽度渐变控制:使用 lerp(width_tip, width_stem, t) 实现从尖端到杆身的宽度平滑过渡。

箭头图案效果的 Shader Graph 节点设计

核心节点功能概述

在 Unity Shader Graph 中实现箭头图案,需整合路径采样、法线计算、颜色混合等节点,核心功能包括:

  • 路径坐标生成:使用自定义 Shader Function 或数学公式直接计算顶点偏移,无需 UV 贴图。
  • 分段着色控制:根据参数 t 的值判断当前点位于箭头的哪一段(尖端/杆身/尾部),应用不同的颜色混合策略。
  • 法线动画纹理:结合时间变量扰动箭头表面的法线向量,实现流动感的光影效果。
  • 方向响应性:将世界空间的方向向量与模型法线对比,计算阴影和高亮强度。

关键端口与参数定义

实现箭头图案的核心参数端口设计如下:

端口名称类型功能说明
World PositionVector3输入(只读),模型顶点的世界空间坐标
NormalVector3输入(只读),表面法线向量
TimeFloat输入(只读),实时时间变量,驱动纹理流动
Arrow DirectionVector3输入(可调节),箭头指向的方向向量(需归一化)
Arrow SizeFloat输入(可调节),箭头的整体尺寸缩放
Arrow ColorColor输入(可调节),箭头显示颜色,支持 Alpha 通道
Flow SpeedFloat输入(可调节),表面纹理流动速度
Flow DirectionVector2输入(可调节),表面纹理流动方向(如 (1,0) 为 X 轴)
Tip BrightnessFloat输入(可调节),箭头尖端亮度
Stem ColorColor输入(可调节),箭头杆身颜色
Base ColorColor输入(可调节),模型的基础颜色
Out ColorVector4输出,最终的着色器颜色,连接到 Master 节点

箭头图案效果的实现步骤(可复现)

前置准备

  1. 环境要求:Unity 2021.3+,URP 渲染管线,已安装 Shader Graph 插件。
  2. 素材准备:任意平面或曲面模型(Plane/Mesh),用于测试箭头图案效果。
  3. 创建基础 Shader
    • 在 Project 窗口右键 → Create → Shader → Universal Render Pipeline → Lit Shader Graph,命名为 "ArrowPatternShader"。
    • 双击打开 Shader Graph,确认 Master 节点为 URP Lit Master。

步骤 1:构建参数化路径坐标系统

  • 添加一维参数 t:由于箭头是二维形状映射到三维表面,需要生成均匀分布的参数 t ∈ [0,1]

    • 技巧:使用 World Position 的任意一个分量(如 Y 轴)归一化到 [0,1] 范围作为参数 t
    • 公式:t = normalize(position.y),若需多方向参数可组合多个分量。
  • 添加方向向量分解:将 Arrow Direction 分解为 X、Y、Z 分量,用于后续坐标偏移计算。

    • 添加 Split 节点拆分 Vector3 为三个 Float 输出。

步骤 2:生成箭头分段形状函数

  • 尖端区域(t ∈ [0, 1/4]):使用二次曲线模拟尖头形状

    • 坐标偏移公式:offset = cos(4π*t) * Arrow Size * 0.3
    • 宽度收缩:width = lerp(Arrow Size, Arrow Size * 0.2, t*4)
  • 杆身区域(t ∈ [1/4, 3/4]):线性等宽直筒形状

    • 宽度保持:width = lerp(Stem Width, Stem Width, 0)
    • 颜色过渡:color = lerp(TipColor, StemColor, (t - 0.25) / 0.5)
  • 尾部区域(t ∈ [3/4, 1]):使用二次曲线模拟收拢形状

    • 坐标偏移公式:offset = cos(4π*(1-t)) * Arrow Size * 0.3
    • 宽度收缩:width = lerp(Stem Width, Stem Width * 0.1, (1-t)*4)
  • 实现步骤

    1. 添加 Range 节点,生成 [0,1] 的 t 参数。
    2. 添加多个 Greater Than / Less Than 节点判断 t 所在区域。
    3. 针对每个区域添加相应的坐标偏移计算分支。

步骤 3:法线流动纹理叠加

  • 基础法线扰动

    1. 添加 Sine 节点,输入公式为 t * FlowSpeed + Time * FlowSpeed
    2. 将输出与 Flow Direction 点乘后映射到法线 X、Y 分量。
  • 归一化扰动后的法线

    • 添加 Normalize 节点确保扰动后的法线长度仍为 1(否则光照计算错误)。
    • 公式:distortedNormal = normalize(originalNormal + tangentNoise)

步骤 4:颜色混合与最终输出

  • 分段颜色混合

    1. 添加 Multiply 节点,将尖端区域掩码与 Tip Color 相乘。
    2. 添加 Multiply 节点,将杆身区域掩码与 Stem Color 相乘。
    3. 添加 Add 节点合并所有分段颜色。
  • 方向性高光响应

    • 添加 Dot 节点,计算 dot(normal, arrowDirection)
    • 使用 SmoothStep(-0.3, 0.3, dotResult) 生成高光强度掩码。
    • 将高光掩码与白色颜色相乘后与基础颜色相加。
  • 连接到 Master 节点

    1. 将最终混合颜色连接到 URP Lit Master 的 "Base Color" 端口。
    2. 若需流动纹理高亮,同时连接到 "Emission" 端口并调整强度。

步骤 5:保存并应用 Shader

  • 点击 Shader Graph 窗口的 "Save Asset" 保存着色器。
  • 在 Project 窗口右键 → Create → Material,命名为 "ArrowPatternMaterial",将 Shader 赋值。
  • 将该材质赋予场景中的平面或模型,进入 Play 模式即可看到动态箭头图案效果。

箭头图案效果的实战调优与扩展案例

基础案例:单向流动箭头(UI 指示效果)

场景描述

在用户界面或导航系统中实现指向性箭头图案,模拟 UI 指示/路径指引的视觉特征。

调整步骤

  1. 设置方向向量:将 Arrow Direction 设为 (0,1,0) 指向上方。
  2. 调整参数
    • Arrow Size:设为 1.5(适中的箭头尺寸)。
    • Flow Speed:设为 1(缓慢流动)。
    • Tip Brightness:设为 1.5(尖端更亮,增强指向性)。
    • Stem Color:设为 (0.7,0.8,0.9,1)(浅灰色杆身)。

进阶案例:多方向旋转箭头(雷达指示效果)

场景描述

实现多个箭头围绕中心旋转的图案,模拟雷达扫描/方向指示器的视觉特征。

实现步骤

  1. 创建多组箭头分支

    • 复制基础箭头计算节点网络。
    • 每组分支设置不同的 Arrow Direction(如 (1,0,0), (0,1,0), (-1,0,0))。
    • 使用 Add 节点叠加三组箭头颜色。
  2. 旋转动画

    • 添加 Sin 节点,公式为 rotAngle = Time * RotSpeed
    • 将 rotAngle 与每个箭头的方向向量点乘实现绕原点旋转效果。

高阶案例:粒子轨迹箭头(游戏寻路效果)

场景描述

在游戏场景中显示从起点到终点的动态箭头轨迹,用于寻路/移动指示。

实现步骤

  1. 起点终点坐标

    • 添加两个 Constant 节点分别设置起点和终点坐标。
    • 使用 Lerp 节点:pos = lerp(startPos, endPos, t)
  2. 轨迹宽度变化

    • 起点附近宽,中间窄,终点又变宽的形态。
    • 公式:width = tipWidth + (1-2*|t-0.5|) * stemWidth

箭头图案效果的使用技巧与注意事项

空间坐标选择

  • 对象空间(Object Space):箭头图案随模型整体移动,适合角色 UI、道具指示。
  • 世界空间(World Space):箭头固定于场景,适合地面路径、环境指引。
  • UV 坐标空间:若模型有 UV 贴图,可直接使用 UV 的 U 或 V 分量作为参数 t,避免归一化计算。

性能优化

  • 减少分段数:基础三段(尖/杆/尾)已足够表现箭头形态,过多分段增加 GPU 开销。
  • 复用 Shader Function:将箭头形状计算封装为独立 Function,便于多模型共享。
  • 控制流动频率:Flow Speed 建议不超过 3,避免高频扰动影响性能。

视觉增强技巧

  • 渐隐效果:添加 SmoothStep 节点,实现箭头边缘的柔和过渡。
  • 扫描闪烁:在 Time 后添加 Sin 节点,控制亮度的周期性脉动。
  • 深度衰减:结合 Depth 节点,使远距离的箭头透明度降低。

常见问题排查

  • 箭头形状变形:检查坐标归一化是否正确(确保 t ∈ [0,1]),确认方向向量已归一化。
  • 箭头不流动:检查 Time 节点是否连接正确,Flow Speed 值是否过小。
  • 颜色混合异常:确保各分支掩码相加不超过 1,使用 Clamp 限制输出范围。

箭头图案效果的拓展应用

总结

Unity Shader Graph 中的箭头图案效果核心是通过 "参数化路径分段 + 法线流动纹理 + 方向响应性",实现从静态到动态的视觉转换。通过调整形状函数、颜色混合策略、流动速度等参数,可适配 UI 指示、雷达显示、游戏寻路等多种场景需求。

拓展应用

  • 交互高亮:结合射线检测,当箭头指向玩家角色时,触发发光/变色反馈。
  • 进度指示:将参数 t 与游戏进程绑定,实现动态增长的箭头(如技能冷却倒计时)。
  • 路径规划可视化:将寻路节点的序列用箭头串联,显示最优路径。
  • 全息界面元素:结合 Fresnel 效果,使箭头呈现半透明全息质感。

【Unity Shader Graph 使用与特效实现】专栏 - 直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)