Unity3D 进阶教程 - 08 Shader Graph 与着色器基础

概述

着色的本质是 计算每个像素的颜色。入门系列中,我们直接使用 URP/Lit 或 URP/Unlit 材质,调整现成参数。

但真实项目中,经常需要自定义视觉效果——溶解消失、能量护盾、全息投影、描边效果等。理解着色器的工作原理,能够从”调参数”升级为”创造效果”。

本篇先掌握 Shader Graph 的可视化编程,然后过渡到 HLSL 自定义节点

1. Shader Graph 基础

Shader Graph 是 URP 内置的可视化着色器编辑器,无需写代码就能创建着色器。

1.1 创建 Shader Graph

  1. Project 窗口 -> Create -> Shader Graph -> URP -> Lit Shader Graph / Unlit Shader Graph
    • Lit:受光照影响(适合场景物体)
    • Unlit:不受光照影响(适合 UI、粒子、特效)

1.2 基本节点

节点 功能
Time 时间相关值
Position 对象/世界/视图空间位置
UV 纹理坐标
Sample Texture 2D 采样纹理
Lerp 线性插值
Multiply/Add 数学运算
Noise 噪声生成
Step 阈值比较
Split 拆分向量

1.3 溶解 Shader 示例

目标:物体从边缘到中心逐渐消融,边缘有发光效果。

节点连接:

1
[ Noise Simple 2D ] -> [ Step (Edge = Time) ] -> [ Alpha Clip Threshold ]
  1. 创建 Unlit Shader Graph
  2. 添加 Simple Noise 节点,连接 UV
  3. 添加 Time 节点
  4. 添加 Step 节点,Noise Out 到 In,Time 到 Edge
  5. Step Out 连接到 Alpha
  6. Alpha Clip Threshold 赋值 0.5

2. 自定义 HLSL 节点

Shader Graph 支持嵌入 HLSL 代码,当可视化节点无法满足复杂逻辑时使用。

2.1 示例:全息投影效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Hologram_float(
float3 WorldPosition,
float3 WorldNormal,
float3 ViewDirection,
float Time,
float ScanLineDensity,
float FlickerSpeed,
out float3 Emission,
out float Alpha
)
{
float scanLine = sin(WorldPosition.y * ScanLineDensity + Time * 5) * 0.5 + 0.5;

float rim = 1.0 - saturate(dot(normalize(WorldNormal), normalize(ViewDirection)));
rim = pow(rim, 2);

float flicker = sin(Time * FlickerSpeed) * 0.1 + 0.9;

float3 baseColor = float3(0.2, 0.8, 1.0);
Emission = baseColor * (scanLine * 0.5 + rim * 0.8) * flicker;
Alpha = scanLine * 0.6 + 0.4;
}

在 Shader Graph 中引入 Custom Function 节点,Type 选择 File,引用上述 .hlsl 文件。


3. 从 Shader Graph 到纯 HLSL

当项目对性能要求极高时,直接写 HLSL 着色器(.shader 文件)能完全控制编译结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Shader "Custom/UnlitGlow"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_GlowIntensity ("Glow Intensity", Range(0, 5)) = 1
}

SubShader
{
Tags { "RenderType"="Transparent" "RenderPipeline"="UniversalPipeline" }

Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};

struct Varyings
{
float4 positionCS : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};

CBUFFER_START(UnityPerMaterial)
float4 _Color;
float _GlowIntensity;
CBUFFER_END

Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.worldNormal = TransformObjectToWorldNormal(IN.normalOS);
OUT.worldPos = TransformObjectToWorld(IN.positionOS.xyz);
return OUT;
}

half4 frag(Varyings IN) : SV_Target
{
float3 viewDir = normalize(GetCameraPositionWS() - IN.worldPos);
float rim = 1.0 - saturate(dot(normalize(IN.worldNormal), viewDir));
rim = pow(rim, 2) * _GlowIntensity;

return _Color * (1 + rim);
}
ENDHLSL
}
}
}

Shader Graph vs 纯 HLSL

对比 Shader Graph 纯 HLSL
学习曲线 低(可视化)
开发效率
性能控制 中等 完全控制
变体管理 自动 手动

总结

  • Shader Graph 是 URP 的可视化着色器编辑器,适合大部分自定义效果
  • 自定义 HLSL 节点 扩展 Shader Graph 的极限
  • 理解坐标空间(Object/World/View)是着色器的基础
  • 常用效果:溶解、菲涅尔、流动纹理、全息投影都有固定的节点模式

下一篇将探讨 后处理特效实战,掌握 URP Volume 系统的深度使用。

ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: