Unity Shader 冰面 Shader 制作原理与流程

这个 Shader 的目标不是「画一张冰贴图」,而是用 多层纹理 + 视差采样 + PBR 光照 + 深度透明 组合,在实时渲染里模拟冰的 体积感、内部吸收、表面高光和边缘融合。


一、真实冰面有哪些视觉特征?

特征 表现 Shader 对应
半透明体积 能看到内部,厚处更暗 十层 _Ice_Gloss 视差采样 + 内部变暗
表面高光 光滑、有反射 高 Smoothness + 环境反射
微观结构 冰晶、裂纹、起伏 _Normal 法线贴图
局部脏/暗 夹杂物、气泡 _AOMap
边缘柔和 与地形/水面自然衔接 场景深度差 Alpha
局部发光 内部散射、蓝调 _EmissionMap

Shader 把上述特征拆成 4 条独立管线,最后在 PBR 里合成。


二、整体流程

渲染状态:Transparent 队列、ZWrite Off、Alpha 混合,所以冰是「盖在场景上」的透明层,而不是不透明固体。


三、核心模块详解

1. 基础色(冰的本体颜色)

baseColor = MainColor × BaseMap × BaseMapIntensity

  • _BaseMap:冰的整体色调、纹理变化(偏蓝、偏白、裂纹底色等)
  • _MainColor:整体染色
  • _BaseMapIntensity:亮度倍增(Ice2 材质里约 9,让冰更亮、更「透」)

这是后续所有效果的底色。


2. 内部深度模拟(最关键的部分)

真实冰里,光穿过内部时会因杂质、气泡、厚度而被 吸收/散射,厚或脏的地方更暗。Shader 用 伪体积采样 来近似,而不是真 3D 体渲染。

原理:视差 + 多层连乘

视线 → 切线空间 → parallaxDir (viewDirTS.xy)

每层 UV 偏移 = uv × Tiling + depthOffset × parallaxDir

depthOffset 每层累加 _DepthValue

10 层 _Ice_Gloss.r 连乘 → depthMask

示意(侧视):

表面 ─────────────────────────

↘ 视线

层1 层2 层3 ... 层10 ← 每层采样 _Ice_Gloss,UV 沿视线方向偏移

● ● ● ●

  • _Ice_Gloss:内部结构噪声(亮=更「透/空」,暗=更「实/厚」)
  • _DepthValue:每层步进(约 -0.0007,负值控制偏移方向)
  • _Ice_GlossTiling:噪声缩放
  • 10 层连乘:一层偏暗会拉低整体 → 模拟「穿过多层都遇到吸收」
内部变暗公式

darkened = baseColor × (1 - saturate(pow(depthMask, DepthIntensity)))

albedo = lerp(darkened, baseColor, FinalColorLerp)

参数 作用
_DepthIntensity 变暗强度;越大内部对比越强
_FinalColorLerp 在「全暗内部」和「原色」之间混合;0=完全内部效果,↑=更亮、更平

为什么用连乘而不是相加?

连乘更像「每层都有概率被吸收」;任一层很暗,整体就明显变暗,体积感更强。


3. 表面 PBR(看起来像冰,而不是塑料)

内部颜色算完后,仍走 URP 标准 Lit PBR:

参数 来源 含义
Normal _Normal × _NormalScale 表面微观起伏、反射方向
Smoothness (1 - IceRougness.r) × SmoothNess 越光滑高光越强
Occlusion _AOMap.r 缝隙/脏区变暗
Emission _EmissionMap × EmissionIntensity 内部散射、蓝调
Metallic 固定 0 冰是电介质,不是金属
Specular 固定 0.5 中等镜面反射

最后调用 UniversalFragmentPBR:主光、附加光、阴影、环境反射、Fog 都由 URP 处理。


4. 深度透明(边缘与接触面融合)

alpha = saturate((sceneDepth - pixelDepth) / DepthFadeDistance)

  • sceneDepth:屏幕该像素处 背后场景 的深度
  • pixelDepth:冰表面自身的深度
  • 差值大(冰浮在水面/悬空)→ Alpha 高 → 更实
  • 差值小(冰贴着地面/与其他面重合)→ Alpha 低 → 更透、边缘化开

这是 Soft Depth Fade,避免冰与地形交接处出现硬边。


四、三条 Render Pass

Pass 作用
Forward 主渲染:算冰面颜色 + 透明 Alpha
DepthOnly 写深度缓冲,供后续效果使用
DepthNormals 输出法线,供 SSAO 等

Forward 关 ZWrite,DepthOnly 开 ZWrite,是透明物体常见配置。


五、制作与调参流程(美术向)

Step 1:准备贴图

贴图 建议内容
BaseMap 冰整体色调、大尺度变化
Ice_Gloss 内部噪声(Grayscale),亮=疏松,暗=致密
Normal 表面冰晶/起伏
IceRougness 粗糙度(亮=糙,暗=滑)
AOMap 裂缝、脏污遮挡
EmissionMap 可选,内部蓝调/亮点

Step 2:基础外观

  1. _MainColor(偏冷蓝/青白)
  2. _BaseMapIntensity 控制整体亮度
  3. _Normal_SmoothNess 定表面质感

Step 3:内部体积感

  1. _DepthIntensity ↑ → 内部明暗对比增强
  2. _DepthValue 控制视差步长(观察角度变化时内部纹理位移)
  3. _FinalColorLerp 控制「有多像实心冰 vs 有多亮」

Step 4:边缘融合

  1. _DepthFadeDistance(Ice2 约 0.4)
  2. 太小→过渡硬;太大→整体发虚

Step 5:场景验证

  • 不同角度:视差是否自然
  • 与地形/水面交界:是否有硬边
  • 光照变化:高光 + 环境反射是否合理

六、设计思路小结

冰面效果 = 体积假阴影(Ice_Gloss 视差)

  • 标准 PBR 表面(Normal / Roughness / AO)

  • 深度透明(与场景融合)

  • 可选自发光(内部散射)

没有真体积渲染或光线步进,而是用 10 层 2D 视差采样 近似体积吸收------在手游/实时场景里,这是 性能与效果 之间较平衡的做法。

相关推荐
鼎艺创新科技13 小时前
不依赖 UE/Unity:我们如何从零搭建一套国产三维 GIS 渲染引擎
人工智能·算法·unity·游戏引擎·三维电子沙盘
新手unity自用笔记20 小时前
unity基于Socket的网络学习
网络·网络协议·学习·unity·c#·游戏引擎
心前阳光1 天前
Unity之XR Interaction Toolkit | IPointerDownHandler问题
unity·游戏引擎·xr
帅_shuai_2 天前
unity 静态字段内存查找工具
unity·游戏引擎
郝学胜-神的一滴2 天前
[简化版 GAMES 104] 现代游戏引擎 06:从Tick时序到邮局模型,拆解确定性世界的底层密码
开发语言·c++·游戏引擎·图形渲染·软件开发·opengl
鹿野素材屋3 天前
Unity超轻量级中文语音播报,仅5兆大小,无需联网即可使用,适用于弹幕、提示等动态语音播出
unity·游戏引擎
电子云与长程纠缠4 天前
UE5 Lyra PocketWorld进行3D内容UI预览 - 上
开发语言·学习·3d·ue5·游戏引擎
玖玥拾4 天前
Unity3D RPG 入门项目(八)游戏设置面板、帧率控制、快捷技能药品栏、技能解锁系统
游戏·3d·unity·游戏引擎
ellis19704 天前
u3d插件xLua[十] lua侧判空问题
unity
牛哇网络工作室4 天前
UnityHDRP写实数字人全流程基础5—语音输入和语音识别
android·unity·c#·游戏引擎·aigc·语音识别·xcode