概述
着色的本质是 计算每个像素的颜色。入门系列中,我们直接使用 URP/Lit 或 URP/Unlit 材质,调整现成参数。
但真实项目中,经常需要自定义视觉效果——溶解消失、能量护盾、全息投影、描边效果等。理解着色器的工作原理,能够从”调参数”升级为”创造效果”。
本篇先掌握 Shader Graph 的可视化编程,然后过渡到 HLSL 自定义节点。
1. Shader Graph 基础
Shader Graph 是 URP 内置的可视化着色器编辑器,无需写代码就能创建着色器。
1.1 创建 Shader Graph
- 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 ]
|
- 创建 Unlit Shader Graph
- 添加 Simple Noise 节点,连接 UV
- 添加 Time 节点
- 添加 Step 节点,Noise Out 到 In,Time 到 Edge
- Step Out 连接到 Alpha
- 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 系统的深度使用。