【动态着色】Unity实现3D扫描线

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

3D 扫描线效果的核心原理与数学基础

扫描线的视觉本质与空间映射

3D 扫描线效果本质是在三维空间中构建周期性的线性纹理,并结合空间坐标与时间变量,模拟出 "扫描" 的动态视觉特征。其核心数学逻辑围绕以下两点展开:

  • 空间周期性:利用三角函数(正弦 / 余弦)的周期性,在模型的世界空间 / 对象空间坐标上构建等间距的线性条纹,扫描线的间距、角度由三角函数的频率和相位控制。
  • 动态扫描驱动:将时间变量融入三角函数计算,使周期性条纹沿指定方向(如 X 轴、Y 轴、自定义方向)持续移动,形成 "扫描" 的动态效果。

关键数学特性

  • 线性映射 :将三维空间坐标(如世界空间的 Y 坐标)映射到一维的三角函数输入,实现 "线" 状纹理的生成,公式简化为:scanLine = sin(spaceCoord * frequency + time * speed)
  • 值域约束:三角函数输出值域为 -1,1,通过值域映射可将其转换为 0,1 的灰度值,或直接作为遮罩控制扫描线的显示 / 隐藏、亮度变化。
  • 方向可控性 :通过对空间坐标的分量组合(如X*cos(angle) + Z*sin(angle)),可实现任意角度的扫描线方向,满足不同场景的视觉需求。

3D 扫描线效果的 Shader Graph 节点设计

核心节点功能概述

在 Unity Shader Graph 中实现 3D 扫描线,需整合空间坐标、时间、三角函数、值域映射等节点,核心功能包括:

  • 空间坐标采样:获取模型的世界空间 / 对象空间坐标,作为扫描线的空间基准,支持不同空间下的扫描效果(对象空间扫描随模型移动,世界空间扫描固定于场景)。
  • 动态时间驱动:通过 Time 节点获取实时时间,控制扫描线的移动速度和节奏,支持速度调节、方向反转。
  • 周期性条纹生成:利用 Sine 节点构建周期性纹理,结合频率参数控制扫描线间距,相位参数控制初始偏移。
  • 阈值与遮罩处理:通过 Step 节点 / Threshold 节点将三角函数输出转换为二值化的扫描线遮罩,或通过 Remap 节点调整扫描线的亮度、宽度。
  • 颜色叠加:将扫描线遮罩与基础颜色 / 自发光颜色叠加,实现扫描线的视觉呈现,支持扫描线颜色自定义、透明度调节。

关键端口与参数定义

实现 3D 扫描线的核心参数端口设计如下:

表格

端口名称 类型 功能说明
World Position Vector3 输入(只读),模型顶点的世界空间坐标,作为扫描线的空间基准
Time Float 输入(只读),实时时间变量,驱动扫描线的动态移动
Scan Frequency Float 输入(可调节),扫描线的频率,控制线条间距(值越大,线条越密集)
Scan Speed Float 输入(可调节),扫描线的移动速度(值为负时反向移动)
Scan Direction Vector2 输入(可调节),扫描线的移动方向(如 XZ 轴方向,默认 (0,1) 为沿 Z 轴扫描)
Scan Color Color 输入(可调节),扫描线的显示颜色,支持 Alpha 通道控制透明度
Scan Width Float 输入(可调节),扫描线的宽度(值越大,线条越粗)
Base Color Color 输入(可调节),模型的基础颜色,扫描线将叠加于该颜色之上
Out Color Vector4 输出,最终的着色器颜色,用于连接到 Master 节点的 Base Color/Emission 端口

3D 扫描线效果的实现步骤(可复现)

前置准备

  1. 环境要求:Unity 2021.3+,URP(Universal Render Pipeline)渲染管线,已安装 Shader Graph 插件。
  2. 素材准备:任意 3D 模型(如 Cube、Sphere、角色模型),用于测试扫描线效果。
  3. 创建基础 Shader:
    • 在 Project 窗口右键 → Create → Shader → Universal Render Pipeline → Lit Shader Graph,命名为 "3DScanLineShader"。
    • 双击打开 Shader Graph,确认 Master 节点为 URP Lit Master。

步骤 1:获取空间坐标与时间变量

  • 添加 World Position 节点:右键搜索 "World Position" 并添加,该节点输出模型每个顶点的世界空间坐标(x,y,z)。
  • 添加 Time 节点:右键搜索 "Time" 并添加,选择 "Time > Float"(取 Time 节点的 Time 分量,线性递增的时间值)。
  • 添加 Vector2 节点:命名为 "Scan Direction",默认值设为 (0,1)(沿 Z 轴扫描),作为扫描线的移动方向基准。

步骤 2:构建扫描线的周期性纹理

  • 坐标投影 :将 3D 空间坐标投影到扫描方向的 2D 平面,实现步骤:
    1. 添加 "Split" 节点,拆分 World Position 的 X、Z 分量(如需沿 Y 轴扫描则拆 X、Y)。
    2. 添加 "Multiply" 节点,将 Split 后的 X 分量与 Scan Direction 的 X 分量相乘,Z 分量与 Scan Direction 的 Z 分量相乘。
    3. 添加 "Add" 节点,将上述两个 Multiply 的结果相加,得到投影后的一维坐标(命名为 "ProjectedCoord")。
  • 周期性计算
    1. 添加 "Multiply" 节点,将 ProjectedCoord 与 "Scan Frequency"(新建 Float 节点,默认值设为 10)相乘,控制扫描线间距。
    2. 添加 "Multiply" 节点,将 Time 节点的输出与 "Scan Speed"(新建 Float 节点,默认值设为 2)相乘,控制扫描移动速度。
    3. 添加 "Add" 节点,将上述两个 Multiply 的结果相加,作为 Sine 节点的输入(命名为 "SineInput")。
    4. 添加 "Sine 节点",将 SineInput 连接到 In 端口,输出周期性的波动值(值域 -1,1)。

步骤 3:扫描线的宽度与遮罩生成

  • 值域映射
    1. 添加 "Remap" 节点,将 Sine 节点的输出(Input Min=-1, Input Max=1)映射到(Output Min=0, Output Max=1),得到 0,1 范围的灰度值。
  • 宽度控制
    1. 添加 "Threshold" 节点(或 Step 节点),将 Remap 的输出连接到 In 端口,新建 Float 节点 "Scan Width"(默认值设为 0.1)连接到 Threshold 端口。
    2. Threshold 节点会将输入值大于阈值的部分输出 1,小于的部分输出 0,实现二值化的扫描线遮罩(值越小,扫描线越细)。

步骤 4:颜色叠加与最终输出

  • 扫描线颜色混合
    1. 添加 "Multiply" 节点,将 Scan Color(新建 Color 节点,默认值设为 (0,1,1,1),青色)与 Threshold 的输出(遮罩)相乘,得到扫描线的颜色(非扫描线区域为黑色)。
    2. 添加 "Multiply" 节点,将 Base Color(新建 Color 节点,默认值设为 (0.2,0.2,0.2,1),深灰色)与(1 - Threshold 输出)相乘,得到基础颜色(扫描线区域为黑色)。
    3. 添加 "Add" 节点,将上述两个 Multiply 的结果相加,得到最终的混合颜色。
  • 连接到 Master 节点
    1. 将最终混合颜色的输出连接到 URP Lit Master 节点的 "Base Color" 端口;若需扫描线自发光,可同时连接到 "Emission" 端口,并调整 Emission 的强度。

步骤 5:保存并应用 Shader

  • 点击 Shader Graph 窗口的 "Save Asset" 保存着色器。
  • 在 Project 窗口右键 → Create → Material,命名为 "3DScanLineMaterial",将 Shader 赋值为上述创建的 "3DScanLineShader"。
  • 将该材质赋予场景中的 3D 模型(如 Cube、Sphere),进入 Play 模式即可看到动态扫描线效果。

3D 扫描线效果的实战调优与扩展案例

基础案例:沿 Y 轴的垂直扫描线(角色扫描效果)

场景描述

在游戏中实现角色的 "3D 扫描" 效果,扫描线沿 Y 轴(垂直方向)移动,模拟安检 / 科技扫描的视觉特征。

调整步骤

  1. 修改扫描方向:将 Scan Direction 节点的 X 设为 1,Y 设为 0(沿 X 轴投影),或直接将 World Position 的 Y 分量作为 ProjectedCoord(沿 Y 轴扫描)。
  2. 调整参数:
    • Scan Frequency:设为 15(线条更密集)。
    • Scan Speed:设为 3(扫描速度更快)。
    • Scan Width:设为 0.05(线条更细)。
    • Scan Color:设为 (0,1,0,1)(绿色),模拟科技感。
  3. 增强效果:将扫描线颜色连接到 Emission 端口,Emission 强度设为 2,使扫描线发光,暗场景下更突出。

进阶案例:环形扫描线(场景范围扫描)

场景描述

实现以某点为中心的环形 3D 扫描线,模拟雷达扫描效果,扫描线沿圆周方向扩散。

实现步骤

  1. 替换空间坐标计算:
    • 添加 "Position" 节点,选择 "Object Space"(对象空间坐标)。
    • 添加 "Distance" 节点,计算 Object Space 坐标到模型中心(0,0,0)的距离:将 Object Space 节点连接到 Distance 的 In 端口,第二个端口设为 Vector3 (0,0,0)。
    • 将 Distance 的输出作为 Sine 节点的输入(替代原 ProjectedCoord),公式改为:sin(distance * frequency + time * speed)
  2. 参数调整:
    • Scan Frequency:设为 8(环形线条间距)。
    • Scan Speed:设为 5(环形扩散速度)。
    • Scan Width:设为 0.1(环形线条宽度)。
  3. 效果增强:添加 "Fresnel Effect" 节点,将 Fresnel 的输出与扫描线遮罩相乘,使边缘的扫描线更亮,增强 3D 层次感。

高阶案例:多方向扫描线叠加(复杂科技效果)

场景描述

叠加多个不同方向、不同速度的扫描线,实现复杂的 "全息扫描" 效果,用于科幻场景的道具 / 场景装饰。

实现步骤

  1. 复制基础扫描线的节点网络(ProjectedCoord → Sine → Threshold),创建 2-3 组独立的扫描线计算分支。
  2. 每组分支调整参数:
    • 分支 1:Scan Direction=(1,0)(沿 X 轴),Scan Speed=2,Scan Frequency=10,Scan Color=(1,0,1)(紫色)。
    • 分支 2:Scan Direction=(0,1)(沿 Z 轴),Scan Speed=-1.5(反向),Scan Frequency=12,Scan Color=(0,1,1)(青色)。
    • 分支 3:Scan Direction=(1,1)(沿 X+Z 轴),Scan Speed=3,Scan Frequency=8,Scan Color=(1,1,0)(黄色)。
  3. 混合多组扫描线:将每组的扫描线颜色通过 "Add" 节点叠加,再与基础颜色混合,实现多色交错的扫描效果。

3D 扫描线效果的使用技巧与注意事项

空间坐标选择

  • 对象空间(Object Space):扫描线随模型移动而移动,适合角色、道具的扫描效果。
  • 世界空间(World Space):扫描线固定于场景,模型移动时扫描线穿过模型,适合场景范围的雷达扫描、区域检测效果。
  • 视图空间(View Space):扫描线随相机视角变化,适合第一人称视角的扫描特效(如瞄准镜扫描)。

性能优化

  • 减少节点复杂度:将重复的计算逻辑(如坐标投影、值域映射)封装为 "Sub Graph",减少主 Shader Graph 的节点数量,降低 GPU 计算开销。
  • 控制频率与精度:移动平台下,Scan Frequency 建议不超过 20,避免过度密集的计算;Time 节点可使用 "Time> Smooth Time" 替代线性 Time,减少机械感的同时降低计算波动。
  • LOD 适配:为不同 LOD 等级的模型设置不同的扫描线参数(低 LOD 降低频率、增大宽度),减少低精度模型的计算量。

视觉增强技巧

  • 扫描线渐变 :将 Threshold 节点替换为 "Smooth Step" 节点,实现扫描线边缘的渐变效果,避免生硬的二值化边界,公式:smoothstep(threshold - 0.05, threshold + 0.05, remapValue)
  • 扫描闪烁 :在 Time 节点后添加 "Sin" 节点,控制扫描线的亮度周期性变化,公式:scanIntensity = 1 + 0.5 * sin(time * 5),再将该值与扫描线颜色相乘。
  • 深度衰减 :结合 "Depth" 节点,使远距离的扫描线透明度降低,增强空间层次感,公式:scanAlpha = 1 - (depth / maxDepth)

常见问题排查

  • 扫描线不显示:检查 Threshold 节点的阈值是否合理(建议 0.01~0.5),确认空间坐标的投影方向是否正确(如沿 Y 轴扫描却用了 XZ 坐标)。
  • 扫描线卡顿:降低 Scan Frequency 值,或使用 "Time> Delta Time" 替代实时 Time,避免帧率波动导致的扫描速度不均。
  • 扫描线方向错误:调整 Scan Direction 的分量(如沿 X 轴扫描设为 (1,0),沿对角线设为 (1,1)),或更换空间坐标(如 Object Space 替代 World Space)。

总结与拓展应用

总结

Unity Shader Graph 中的 3D 扫描线效果核心是通过 "空间坐标投影 + 三角函数周期性 + 时间动态驱动",实现从静态条纹到动态扫描的视觉转换。通过调整频率、速度、方向、颜色等参数,可适配角色扫描、雷达探测、全息投影、科技场景装饰等多种游戏 / 可视化需求,且节点化的实现方式无需编写手写 Shader,降低了开发门槛。

拓展应用

  • 扫描高亮交互:结合射线检测,当扫描线经过模型的特定区域时,触发高亮 / 变色效果,用于解谜游戏的线索提示。
  • 扫描数据可视化:将扫描线的亮度 / 颜色与模型的顶点数据(如法线、曲率)绑定,实现 3D 模型的数据分析可视化(如工业检测、医疗扫描)。
  • 扫描后效叠加:将扫描线效果与屏幕后处理(如 Glitch、Vignette)结合,模拟扫描时的信号干扰、画面畸变,增强科技感。
  • 多通道扫描:将扫描线分为红、绿、蓝三个通道,分别控制不同的移动速度和方向,实现 RGB 分离的扫描特效,用于赛博朋克风格场景。

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

相关推荐
SmalBox1 天前
【动态着色】Unity 实现消融效果
unity3d·游戏开发·图形学
_zhourui_h_1 天前
我以为 ECSList 已经够快了,直到我直接拿到了 Column
unity3d
SmalBox2 天前
【动态着色】Unity 实现全息投影着色器
unity3d·游戏开发·图形学
SmalBox3 天前
【动态着色】Unity 实现箭头图案
unity3d·游戏开发·图形学
SmalBox4 天前
【扭曲着色器】Unity实现-黑洞扭曲效果
unity3d·游戏开发·图形学
k4m7v2pz4 天前
Godot 4 仿 agar.io 卡顿优化:用空间网格把 30 万次碰撞检测降到几千次
性能优化·godot·游戏开发·碰撞检测·空间网格
k4m7v2pz4 天前
Godot 4 嵌入式试玩窗口尺寸与适配策略详解
编辑器·游戏引擎·godot·游戏开发·嵌入式运行
SmalBox5 天前
【扭曲着色器】Unity实现-冰纹理折射
unity3d·游戏开发·图形学
vivo互联网技术5 天前
vivo 广告小游戏:从"写代码"到"说需求"
前端·人工智能·游戏开发