【动态着色】Unity 实现全息投影着色器

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

全息投影着色器效果的核心原理与数学基础

全息投影的视觉本质与空间映射

全息投影特效的核心在于模拟 菲涅尔折射 + 干涉条纹 + 相位调制 的光学现象,通过 Shader Graph 实现虚拟的透明介质对光波的调制效果。其核心数学逻辑围绕以下两点展开:

  • 菲涅尔透射率:利用菲涅尔方程 F(θ) = (n1*cos(θi) - n2*cos(θt))² / (n1*cos(θi) + n2*cos(θt))² 计算介质表面随视角变化的透光率,实现边缘更亮、中心更暗的视觉效果。
  • 干涉条纹生成:通过叠加两束虚拟光波的相位差 Δφ = k * (r1 - r2),模拟全息图上的莫尔条纹,公式简化为 interference = sin(ω*(x*cos(α) + y*sin(β)) - ω*time)

关键数学特性

  • 折射率映射:将物理折射率 n 映射到 Shader 中的传输系数 T,使用 T = 1 - F 实现透光与反射的动态平衡。
  • 干涉条纹频率:控制全息图条纹密度,公式为 frequency = stripesPerUnit / worldScale
  • 相位调制:通过顶点偏移 vertexOffset = amplitude * sin(frequency*UV + phaseOffset) 模拟光波前畸变。

全息投影着色器效果的 Shader Graph 节点设计

核心节点功能概述

在 Unity Shader Graph 中实现全息投影,需整合菲涅尔计算、干涉条纹生成、相位调制等节点,核心功能包括:

  • 菲涅尔遮罩生成:基于视角与法线的夹角计算半透明度,使用 dot(viewDirection, normal) 获得余弦值。
  • 莫尔条纹叠加:叠加两组不同频率的正弦波,模拟全息图的网格干涉效果。
  • 颜色混合策略:将透射颜色、反射颜色和背景颜色按菲涅尔权重混合,实现虚实结合。
  • 动态调制控制:结合时间变量和顶点位移,实现全息图像的流动感和深度层次。

关键端口与参数定义

实现全息投影的核心参数端口设计如下:

端口名称 类型 功能说明
World Position Vector3 输入(只读),模型顶点的世界空间坐标
Normal Vector3 输入(只读),表面法线向量
View Direction Vector3 输入(只读),从顶点到相机的方向向量
Time Float 输入(只读),实时时间变量,驱动动态调制
Fresnel Power Float 输入(可调节),菲涅尔效果的强度指数
Transmission Color Color 输入(可调节),透射的背景颜色
Reflection Color Color 输入(可调节),表面反射的颜色
Background Color Color 输入(可调节),全息图显示的背景
Interference Frequency Float 输入(可调节),干涉条纹密度
Moiré Offset Vector2 输入(可调节),莫尔条纹的相位偏移
Phase Shift Speed Float 输入(可调节),相位流动速度
Transparency Alpha Float 输入(可调节),整体透明度控制
Hologram Glow Float 输入(可调节),全息发光强度
Base Color Color 输入(可调节),模型的基础颜色
Out Color Vector4 输出,最终的着色器颜色,连接到 Master 节点

全息投影着色器效果的实现步骤(可复现)

前置准备

  1. 环境要求:Unity 2021.3+,URP 渲染管线,已安装 Shader Graph 插件。
  2. 素材准备:透明或半透明材质(如玻璃板/薄塑料),用于测试全息投影效果。
  3. 创建基础 Shader
    • 在 Project 窗口右键 → Create → Shader → Universal Render Pipeline → Lit Shader Graph,命名为 "HologramProjectorShader"。
    • 双击打开 Shader Graph,确认 Master 节点为 URP Lit Master。

步骤 1:计算视角依赖的菲涅尔遮罩

  • 获取相向向量

    • 添加 View Direction 节点:viewDir = normalize(cameraPos - worldPosition)
    • 若无 Camera 节点,可用自定义 Vector3 端口输入相机位置。
  • 菲涅尔强度计算

    1. 添加 Dot 节点,计算 dot(normalize(viewDir), normal)
    2. 使用 Lerp(-1, 1, dotResult) 映射到 [-1,1] 范围(Sine 函数需要对称输入)。
    3. 添加 Pow 节点,公式为 fresnel = pow(abs(Lerp(-1, 1, dotResult)), fresnelPower)
  • 透明度混合

    • 使用 Lerp(transmissionColor, backgroundColor, fresnel * transparencyAlpha)

步骤 2:生成莫尔干涉条纹

  • 第一组条纹(X 轴方向)

    1. 添加 Sine 节点,输入公式为 xStr = Interference Frequency * worldPosition.x + time * Phase Shift Speed
    2. 映射到 [0,1]:xMask = Remap(xStr, -1, 1, 0, 1)
  • 第二组条纹(Y 轴方向)

    1. 添加 Sine 节点,输入公式为 yStr = Interference Frequency * worldPosition.y + time * Phase Shift Speed + MoiréOffset.y
    2. 映射到 [0,1]:yMask = Remap(yStr, -1, 1, 0, 1)
  • 莫尔图案叠加

    1. 添加 Multiply 节点,将 xStr 和 yStr 相乘得到网格效果。
    2. 使用 Sin 对乘积求正弦值实现干涉条纹。
    3. 公式:moire = sin(worldPosition.x * interferenceFreq + worldPosition.y * interferenceFreq - time * phaseSpeed + moiréOffset)

步骤 3:相位调制与顶点偏移

  • 法线扰动模拟

    1. 添加 Split 节点,将 Normal 拆分为 nx、ny、nz 分量。
    2. 使用 Sin 节点对 nx、ny 进行相位调制:distortedNx = sin(nx * interferenceFreq + time * phaseSpeed)
    3. 合并扰动后的法线:distortedNormal = Vector3(distortedNx, distortedNy, nz)
  • 归一化:添加 Normalize 确保法线单位长度。

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

  • 透射 - 反射混合

    1. 添加 Lerp 节点,公式为 mix = Lerp(Reflection Color, Transmission Color, Fresnel)
  • 干涉条纹叠加

    1. 添加 Multiply 节点,将莫尔条纹与透射颜色相乘:transmissionWithMoire = moire * transmissionColor
    2. 添加 Add 节点合并基础混合与干涉效果。
  • 发光效果叠加

    1. 添加 Pow 节点,对菲涅尔强度取幂:glow = fresnelPow(3) * Hologram Glow
    2. 将 glow 连接到 Emission 端口。
  • 连接到 Master 节点:将最终颜色连接到 URP Lit Master 的 "Base Color" 端口,发光效果连接 "Emission"。

步骤 5:保存并应用 Shader

  • 点击 Shader Graph 窗口的 "Save Asset" 保存着色器。
  • 在 Project 窗口右键 → Create → Material,命名为 "HologramProjectorMaterial",将 Shader 赋值。
  • 重要设置:将材质的渲染模式设为 "Transparent"(透明),排序层次设为 "Queue -1"(前置渲染)。
  • 将该材质赋予场景中的平面或薄板模型,进入 Play 模式即可看到全息投影效果。

全息投影着色器效果的实战调优与扩展案例

基础案例:边缘发光全息图(科技扫描舱效果)

场景描述

在科幻游戏中实现类似《赛博朋克 2077》的扫描舱全息界面,边缘高亮发光,中心显示背景信息。

调整步骤

  1. 设置菲涅尔参数

    • Fresnel Power:设为 5(强化边缘发光)。
    • Transparency Alpha:设为 0.8(整体半透明)。
    • Hologram Glow:设为 2(发光强度适中)。
  2. 颜色配置

    • Transmission Color:(0.1,0.3,0.6,0.5)(蓝色透射)。
    • Reflection Color:(0.9,0.9,1,1)(淡银色反射)。
    • Background Color:(0.2,0.4,0.8,0.7)(深空蓝背景)。
  3. 干涉条纹参数

    • Interference Frequency:设为 8(条纹密度适中)。
    • Moiré Offset:(0,1)(Y 轴偏移产生斜向条纹)。
    • Phase Shift Speed:设为 2(中等流动速度)。

进阶案例:多图层全息投影(信息叠加效果)

场景描述

在 UI 层叠展示多组全息信息,每组具有不同的透明度、条纹频率和颜色。

实现步骤

  1. 创建多层分支

    • 复制菲涅尔计算节点网络。
    • 第一层:高频条纹(frequency=12)用于显示详细数据。
    • 第二层:低频条纹(frequency=5)用于背景轮廓。
    • 第三层:无条纹纯色层用于文字显示。
  2. 混合层级

    • 使用 Add 节点叠加各层颜色,设置不同 Alpha 实现深度层次。
    • 公式:finalColor = layer1*(0.7) + layer2*(0.3) + layer3*(0.5)

高阶案例:动态全息投影(信息滚动效果)

场景描述

模拟全息屏幕上滚动的数据流,条纹和相位随时间变化,营造数据流动的视觉特征。

实现步骤

  1. 垂直方向滚动调制

    • 添加 Add 节点到 worldPosition.y:scrollY = worldPosition.y + time * scrollSpeed
    • 将 scrollY 代入条纹公式,实现向上滚动的视觉效果。
  2. 闪烁效果叠加

    • 在菲涅尔遮罩后添加 Sinblink = 0.5 + 0.5*sin(time*3)
    • Multiply 将整体透明度与 blink 相乘,实现周期性亮暗变化。

全息投影着色器效果的使用技巧与注意事项

空间坐标选择

  • 对象空间(Object Space):全息图随模型移动而移动,适合手持设备、可动投影平台。
  • 世界空间(World Space):全息图固定于场景,适合场景装饰、固定信息台。
  • 相机空间(View Space):结合 View Position 节点,使全息图始终面向相机,增强可见性。

性能优化

  • 减少条纹密度:Interference Frequency 建议不超过 15,避免 GPU 高频采样。
  • 复用 Shader Function:将菲涅尔计算封装为独立 Function,便于多个全息表面共享。
  • 控制层数叠加:多图层时限制在 3 层内,超过会显著增加性能开销。

视觉增强技巧

  • 景深模糊:结合 Depth 节点,对远距离的全息图添加模糊效果,增强空间层次。
  • 屏幕泛光:使用 Screen Space Ambient Occlusion(SSAO)或自定义 Screen Glow 节点模拟环境反射。
  • 动态颜色变化:将 Background Color 与场景主色调联动,实现自适应色彩融合。

常见问题排查

  • 全息图不可见:检查材质渲染模式是否为 Transparent,排序层次是否在 Queue -1 到 240 之间。
  • 条纹过于密集:降低 Interference Frequency,或增加世界缩放比例(将 position 除以 scale)。
  • 发光过强导致烧屏:减小 Hologram Glow 值,或在 Emission 前添加 Clamp 限制范围。

全息投影着色器效果的拓展应用

总结

Unity Shader Graph 中的全息投影效果核心是通过 "菲涅尔视角依赖 + 莫尔干涉条纹 + 相位动态调制",实现从物理光学现象到虚拟视觉特效的转换。通过调整透射/反射/背景颜色、条纹频率、发光强度等参数,可适配科幻界面、数据可视化、AR 增强等多种场景需求。

拓展应用

  • AR 全息标记:结合 AR Foundation,将全息图与真实世界锚点绑定,实现增强现实中的虚拟物体投影。
  • 全息菜单 UI:在技能栏/任务菜单中替代传统 UI,使用全息效果提升沉浸感。
  • 动态信息流:将数据更新速率映射到 Phase Shift Speed,快速滚动显示高优先级信息。
  • 多色全息分屏:将不同区域分配 RGB 通道颜色,实现 RGB 分离的全息显示效果,增强赛博朋克风格。

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

posted @ 2026-08-30 11:05  SmalBox  阅读(5)  评论(0)    收藏  举报