掌握 ShaderLab 需要循序渐进地学习,结合理论、实践和工具。以下是一个推荐的学习路径,帮助你从零基础逐步进阶:
阶段一:基础准备 (理解核心概念与环境)
-
必备知识:
- 编程基础: 至少熟悉一种编程语言(C# 或 C++ 最佳),理解变量、函数、控制流等概念。Shader 编程逻辑性很强。
- 数学基础 (尤其重要):
- 向量和矩阵运算: 点积、叉积、矩阵乘法、变换(平移、旋转、缩放)。这是理解顶点变换、光照计算的基础。
- 基础三角函数:
sin
,cos
,tan
等常用于波形、旋转、周期性动画。 - 坐标系: 模型空间、世界空间、观察空间、裁剪空间、屏幕空间。理解顶点如何在不同空间转换。
- 基础线性代数: 理解向量空间、线性变换。
- 图形学基础概念:
- 渲染管线: 理解 CPU 提交数据 -> 顶点着色器 -> 光栅化 -> 片元着色器 -> 输出到屏幕 的流程。明确 Vertex Shader 和 Fragment Shader 的职责。
- 光照模型: 环境光、漫反射 (Lambert)、高光反射 (Phong, Blinn-Phong)。理解光线如何与表面交互。
- 纹理映射: UV 坐标、采样、纹理过滤(点采样、双线性、三线性)。
- 混合: Alpha 混合 (Blend) 原理。
-
Unity 基础:
- 熟悉 Unity 编辑器界面和基本操作。
- 了解材质 (Material) 的概念及其与着色器 (Shader) 的关系。
- 知道如何创建材质球并为其分配着色器。
阶段二:入门 ShaderLab (语法与固定函数着色器)
-
ShaderLab 结构:
- 学习
.shader
文件的基本结构:Shader "Path/Name"
:定义着色器在材质下拉菜单中的路径和名称。Properties
块:定义在材质检视面板中暴露的可调参数(颜色、浮点数、纹理、向量等)。SubShader
块:针对不同渲染路径或硬件级别的实现。Pass
块:一次完整的渲染过程(顶点处理 + 片元处理)。CGPROGRAM
/ENDCG
:包裹 CG/HLSL 代码块(可编程着色器)。Tags
:设置渲染顺序 ("Queue"
)、渲染类型 ("RenderType"
)、是否投射阴影 ("ForceNoShadowCasting"
) 等。LOD
:细节级别。
- 理解
Properties
如何与 CG/HLSL 代码中的变量关联。
- 学习
-
固定函数着色器 (Fixed-Function Shader):
- 目标: 理解早期着色方式,学习 ShaderLab 语法,制作简单效果。
- 内容:
- 使用
SetTexture
命令进行简单的纹理采样和混合。 - 使用
Lighting On
/Material
块实现简单的逐顶点光照(漫反射、环境光)。 - 学习
Color
,ColorMaterial
等命令。
- 使用
- 实践: 编写一个只显示纹理的着色器;编写一个带简单顶点光照的纹理着色器。
阶段三:核心 - CG/HLSL 与可编程着色器 (Vertex & Fragment Shader)
-
CG/HLSL 语言基础:
- 语法:变量声明、数据类型 (
float
,half
,fixed
,float2/3/4
,sampler2D
)、结构体、函数。 - 语义 (Semantics):
POSITION
,NORMAL
,TEXCOORD0
,SV_POSITION
,COLOR
等。理解输入输出数据流。 - 常用内置函数:
mul
(矩阵乘法),dot
(点积),cross
(叉积),normalize
,lerp
(线性插值),tex2D
(纹理采样),saturate
(钳制到 [0,1]) 等。
- 语法:变量声明、数据类型 (
-
顶点着色器 (Vertex Shader):
- 职责: 将模型顶点从模型空间变换到裁剪空间(通过 MVP 矩阵)。
- 计算并传递数据给片元着色器(如:世界空间位置、法线、UV、顶点颜色等)。
- 实现简单的顶点动画(如:波浪、旋转)。
-
片元着色器 (Fragment Shader / Pixel Shader):
- 职责: 计算每个像素(更准确说是片元)的最终颜色。
- 核心内容:
- 纹理采样与应用。
- 光照计算: 实现自定义光照模型(Lambert, Phong, Blinn-Phong, 半兰伯特)。
- 理解
_WorldSpaceLightPos0
,_LightColor0
,UNITY_LIGHTMODEL_AMBIENT
等内置光照变量。 - 法线贴图 (Normal Mapping):使用切线空间法线扰动表面法线,增加细节。
- 透明与混合 (
Blend
命令)。 - 简单的屏幕后处理效果基础(需要结合
OnRenderImage
)。
-
实践项目 (关键!):
- 无光照纯色/纹理着色器。
- 自定义漫反射光照着色器(逐顶点/逐像素)。
- 自定义高光(Phong/Blinn-Phong)着色器。
- 纹理 + 法线贴图着色器。
- 透明着色器(Alpha Blend)。
- 溶解效果 (利用
clip
函数)。 - 简单的顶点动画(如旗帜飘动)。
- 边缘光 (Rim Light) 效果。
阶段四:进阶技术与优化
-
表面着色器 (Surface Shader):
- 理解: Unity 对光照模型的一种高级封装。它帮你处理了光照pass、阴影pass、前向/延迟渲染兼容性等复杂问题,你只需关注表面的属性(反照率、法线、自发光、高光、光滑度、金属度等)和光照函数。
- 学习:
SurfaceOutput
结构体,surf
函数,自定义光照函数LightingXxxx
。 - 适用场景: 需要标准光照(特别是 PBR)且不想手动处理所有pass的情况。非常常用。
- 实践: 实现自定义光照模型的表面着色器(如 Toon 卡通着色)。
-
渲染路径 (Rendering Path):
- 理解前向渲染 (Forward Rendering) 和延迟渲染 (Deferred Rendering) 的区别、优缺点及适用场景。
- 学习如何在 Shader 中处理多光源(前向渲染中的
ForwardAdd
pass)。 - 了解
LightMode
Tag ("ForwardBase"
,"ForwardAdd"
,"Deferred"
)。
-
阴影:
- 理解阴影投射 (
ShadowCaster
pass) 和阴影接收的原理。 - 学习如何让自定义着色器投射和接收阴影(通常需要定义
ShadowCaster
pass 或使用fallback
)。 - 了解
SHADOW_COORDS
,TRANSFER_SHADOW
,SHADOW_ATTENUATION
宏(用于接收阴影)。
- 理解阴影投射 (
-
屏幕空间效果:
- 使用
GrabPass
抓取屏幕内容。 - 实现简单的扭曲、全屏模糊、简单颜色校正等效果。
- 使用
-
光照贴图与全局光照 (GI):
- 学习
LIGHTMAP_ON
宏和DECLARE_LIGHTMAP_COORDS
/TRANSFER_LIGHTMAP
等宏。 - 让着色器支持烘焙光照贴图和实时/烘焙混合光照。
- 学习
-
Shader Graph (可视化工具):
- 目标: 快速搭建效果原型,理解节点化流程,降低复杂 HLSL 代码编写负担。
- 学习: 节点操作、常用节点(数学、纹理、UV、向量、光照节点等)、自定义函数节点、子图 (Sub Graph)。
- 实践: 用 Shader Graph 复现之前用代码写的效果(如溶解、边缘光、简单 PBR)。
-
优化技巧:
- 精度: 合理使用
float
(高精度,32位),half
(中精度,16位),fixed
(低精度,11位) 优化性能和带宽。 - 计算量: 避免复杂计算在片元着色器中进行(尤其移动平台),尽量移到顶点着色器或预计算。使用查找纹理 (Lookup Texture)。
- 分支: GPU 不擅长分支预测,尽量避免片元着色器中的复杂分支 (
if/else
)。 - 纹理采样: 减少采样次数,使用纹理图集 (Texture Atlas)。
- Shader Variants: 理解
#pragma multi_compile
和#pragma shader_feature
产生的变体,避免不必要的变体导致包体膨胀。
- 精度: 合理使用
阶段五:深入与探索
-
高级光照模型:
- 基于物理的渲染 (PBR): 学习金属度/粗糙度工作流或镜面反射/光泽度工作流。理解
Standard
/Standard (Specular setup)
表面着色器背后的原理。 - 次表面散射 (SSS)。
- 各向异性高光。
- 毛发渲染 (Kajiya-Kay)。
- 基于物理的渲染 (PBR): 学习金属度/粗糙度工作流或镜面反射/光泽度工作流。理解
-
高级效果:
- 视差贴图 (Parallax Mapping)。
- 屏幕空间反射 (SSR)。
- 程序化纹理/噪声生成 (Perlin, Simplex)。
- 体积效果(光线步进 Ray Marching)。
- 卡通渲染 (Cel Shading / NPR)。
- 水体效果。
- 地形混合着色器。
-
Compute Shader:
- 利用 GPU 进行通用计算,处理大量并行数据(物理模拟、粒子系统、图像处理等)。
-
Shader Debugging:
- 熟练使用
Frame Debugger
。 - 利用
return float4(someValue, 1);
在片元着色器中输出中间值进行调试。 - 使用
RenderDoc
等外部工具进行深度分析。
- 熟练使用
学习资源推荐
- 官方文档 (必读!):
- Unity Manual - Shaders:
https://docs.unity3d.com/Manual/Shaders.html
- Unity Scripting API - ShaderLab:
https://docs.unity3d.com/Manual/SL-Reference.html
- Built-in Shader Include Files (如
UnityCG.cginc
):阅读源码是学习内置函数和宏的最佳方式。通常位于[Unity安装路径]/Data/CGIncludes
。
- Unity Manual - Shaders:
- 经典书籍/教程:
- 《Unity Shader入门精要》(冯乐乐著) - 中文经典,系统全面。
- 《Unity 2018 Shaders and Effects Cookbook》 - 英文,案例驱动。
- Catlike Coding - Rendering Tutorials (
https://catlikecoding.com/unity/tutorials/rendering/
) - 非常深入、系统的英文教程。 - Ben Cloward’s Shader Development YouTube Channel (
https://www.youtube.com/@BenCloward
) - 大量实用视频教程。
- 社区:
- Unity Forums (Graphics 板块):
https://forum.unity.com/forums/graphics.75/
- ShaderToy (
https://www.shadertoy.com/
) - 学习 GLSL 和前沿效果的宝库(注意语法差异,但思路相通)。 - GitHub:搜索开源项目学习他人代码。
- Unity Forums (Graphics 板块):
- 工具:
- Visual Studio / VS Code (with ShaderlabVSCode / Shader Languages Support 插件): 提供语法高亮、自动补全。
- Shader Graph: Unity 内置可视化着色器编辑器。
- Amplify Shader Editor: 强大的第三方可视化着色器编辑器。
- RenderDoc: 强大的图形调试器。
- Frame Debugger (Unity 内置): 逐帧分析渲染过程。
核心建议
- 动手!动手!动手! 理论必须结合实践。每学一个概念,立即在 Unity 中写代码测试效果。从修改官方内置着色器开始。
- 循序渐进: 不要一开始就追求复杂炫酷的效果。打好数学、图形学基础、理解管线、掌握 Vertex/Fragment Shader 是核心。
- 理解而非死记: 理解渲染管线、光照模型、数学变换背后的原理,比记住具体代码更重要。这样你才能举一反三。
- 善用调试工具: Frame Debugger 和
return float4
调试法是你的好朋友。 - 阅读优秀代码: Unity 内置着色器源码 (
CGIncludes
文件夹) 是极佳的学习材料。 - 关注性能: 尤其在移动平台,时刻考虑优化。了解不同精度类型和计算开销。
- 利用可视化工具: Shader Graph / Amplify 能帮助你快速理解数据流动和效果搭建,但最终要理解其生成的代码逻辑。
- 保持耐心和热情: Shader 学习曲线陡峭,遇到困难是正常的。多查资料,多尝试,多问(清晰的描述问题)。
遵循这个路径,持续学习和实践,你就能逐步掌握 ShaderLab 和 Unity 着色器开发,创造出令人惊叹的视觉特效!祝你学习顺利!