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 视差采样 近似体积吸收------在手游/实时场景里,这是 性能与效果 之间较平衡的做法。

相关推荐
玖玥拾2 小时前
Cocos学习笔记:关卡系统、音频管理与物理控制
游戏引擎·cocos2d
小拉达不是臭老鼠3 小时前
Unity中的UI系统之UGUI_登陆面板实现
ui·unity
郝学胜-神的一滴3 小时前
[简化版 GAMES 101] 计算机图形学 11:频域·卷积·抗锯齿
c++·unity·图形渲染·opengl·three·unreal
玖玥拾12 小时前
Cocos学习笔记:滚动视图、关卡系统与本地存储
游戏引擎·cocos2d
元气少女小圆丶19 小时前
SenseGlove Nova 2+Unity开发笔记2
笔记·unity·游戏引擎
Oiiouui1 天前
Godot(4.x): 游戏管理器: Godot 内注入数据处理与总接口实现
游戏·游戏引擎·godot
想不明白的过度思考者1 天前
Unity学习笔记——虚拟摇杆实现笔记(事件触发器的使用、UGUI 坐标转换)
笔记·学习·unity
魔士于安1 天前
unity volumefog带各种demo第一人称 wsad 穿墙控制
游戏·unity·游戏引擎·贴图·模型
魔士于安1 天前
红色文化馆技术文档
前端·unity·游戏引擎·贴图·模型