目录
包含文件的使用语法
包含文件是以cginc作为扩展名的文本文件
文件所在路径:
Unity安装目录/Editor/Data/CGIncludes/

在编写Shader时,只需要使用编译指令提前把对应的文件包进Shader,就可以直接使用了。
包含文件的声明也要写在CG代码块内,它的语法结构:
{
CGPROGRAM
//......
#include"UnityCG.cginc"
//......
ENDCG
}
只要输入了正确的文件名称,Shader在编译的时候就会自动在这个路径下寻找对应的文件。
UnityCG.cginc
1.顶点着色器输入结构体


2.顶点变换函数
|---------------------------------------------|---------------------|---------------------------------------|
| 函数 | 说明 | 等同于 |
| float4 UnityObjectToClipPos(float3 pos) | 模型空间------>齐次裁剪空间 | mul(UNITY_MATRIX_MVP,float4(pos,1,0)) |
| float3 UnityObjectToViewPos(float3 pos) | 模型空间------>摄像机空间 | mul(UNITY_MATRIX_MV,float4(pos,1,0)) |
| float4 UnityWorldToViewPos(float3 pos) | 世界空间------>摄像机空间 | mul(UNITY_MATRIX_V,float4(pos,1,0)) |
| float3 UnityWorldToClipPos(float3 pos) | 世界空间------>齐次裁切空间 | mul(UNITY_MATRIX_VP,float4(pos,1,0)) |
| float4 UnityViewToClipPos(float3 pos) | 摄像机空间------>齐次裁切空间 | mul(UNITY_MATRIX_P,float4(pos,1,0)) |
3.向量变换函数
|--------------------------------------------------|---------------------|
| 函数 | 说明(已经标准化处理) |
| float4 UnityObjectToWorldDir(float3 dir) | 向量:模型空间------>世界空间 |
| float4 UnityWorldToObjectDir(float3 dir) | 向量:世界空间------>模型空间 |
| float4 UnityObjectToWorldNormal(float3 norm) | 法线:模型空间------>世界空间 |
4.灯光辅助函数
定义了一些计算顶点指向灯光的方向向量
|----------------------------------------------------|-------------------------------------------------|
| float3 UnityWorldSpaceLightDir(in float3 worldPos) | 输入世界空间顶点坐标,返回世界空间中从顶点指向灯光的向量 |
| float3 ObjSpaceLightDir(in float4 v) | 输入模型空间顶点坐标,返回模型空间中从顶点指向灯光的向量 |
| float3 Shade4PointLights(...) | 输入一系列所需变量,返回4个点光源的光照信息,在前向渲染中使用这个函数计算逐顶点的光照 |
5.视角向量函数
|-----------------------------------------|----------------------------------|
| 函数 | 说明(没有被标准化) |
| float3 UnityWorldSpaceViewDir(float3 v) | 输入世界空间顶点坐标,返回世界空间中从顶点指向灯光的向量 |
| float3 ObjSpaceViewDir(float4 pos) | 输入模型空间顶点,返回模型空间中从顶点指向摄像机的向量 |
6.其他辅助函数和宏
|------------------------------------------|--------------------------------------|
| 函数 | 说明 |
| TRANSFORM_TEX(tex,name) | 宏定义,输入UV坐标和纹理名称,得到贴图和纹理坐标 |
| fixed3 UnpackNormal(fixed4 packednormal) | 将法线向量从[0,1]映射到[-1,1] |
| half Luminance(half3 rgb) | 将颜色数据转变为灰度数据 |
| float4 ComputeScreenPos(float4 pos) | 输入裁切空间顶点坐标,**得到屏幕空间纹理坐标,**用于屏幕空间纹理映射 |
| float4 ComputeGrabScreenPos(float4 pos) | 输入裁切空间顶点坐标,得到采样GrabPass的纹理坐标 |
宏定义的语法结构为:
#define name string;
1)#define:表示宏定义的指令
2)name:宏名称,后续可以直接输入名称进行使用
3)string:"在编译前,预处理器会将代码中所有'宏名称',原封不动地替换成它后面定义的'内容'。"

UnityShaderVariables.cginc
1.空间变换矩阵
可以直接使用CG函数mul(Matrix,Vertex)将顶点在不同空间之间进行变换
| 矩阵名称 | 类型 | 变换方向 | 核心用途 | 适用场景 |
|---|---|---|---|---|
UNITY_MATRIX_M |
float4x4 |
模型空间 → 世界空间 | 顶点 / 向量从模型空间转世界空间 | 计算世界空间顶点位置、世界空间法线 |
UNITY_MATRIX_V |
float4x4 |
世界空间 → 视图空间 | 顶点 / 向量从世界空间转摄像机本地(视图)空间 | 计算视图空间视角向量、视图空间光照 |
UNITY_MATRIX_P |
float4x4 |
视图空间 → 裁剪空间 | 顶点从视图空间转裁剪空间(最终输出) | 顶点着色器最终输出 SV_POSITION |
UNITY_MATRIX_MV |
float4x4 |
模型空间 → 视图空间 | 等价于 UNITY_MATRIX_V * UNITY_MATRIX_M |
快速计算视图空间顶点位置(减少矩阵乘法) |
UNITY_MATRIX_MVP |
float4x4 |
模型空间 → 裁剪空间 | 等价于 UNITY_MATRIX_P * UNITY_MATRIX_MV |
顶点着色器直接输出裁剪空间位置(最常用) |
UNITY_MATRIX_T_MV |
float4x4 |
视图空间 → 模型空间(转置) | 向量从视图空间转模型空间(仅方向向量) | 视图空间方向向量转回模型空间 |
UNITY_MATRIX_IT_MV |
float4x4 |
视图空间 → 模型空间(逆转置) | 法向量从视图空间转模型空间(保证垂直性) | 法向量的空间变换(避免拉伸) |
_World2Object |
float4x4 |
世界空间 → 模型空间 | 等价于 UNITY_MATRIX_M 的逆矩阵 |
世界空间向量转回模型空间 |
_Object2World |
float4x4 |
模型空间 → 世界空间 | 和 UNITY_MATRIX_M 完全等价(别名) |
习惯用 _Object2World 的开发者兼容 |
2.时间变量
在实现动态效果的时候经常会使用时间因子作为动态变量,是实现 Shader 动效(如流光、溶解、呼吸灯)的核心基础。
所有时间变量均为 float/float4 类型,单位为秒(s),从游戏启动时开始计时(暂停时停止)。
| 变量名称 | 类型 | 核心含义 | 常用场景 |
|---|---|---|---|
_Time |
float4 |
(t/20, t, t*2, t*3),其中 t = 游戏运行总时间 |
多倍速时间控制(慢速 / 常规 / 快速动效) |
_SinTime |
float4 |
(sin(t/8), sin(t/4), sin(t/2), sin(t)),t = 游戏运行总时间 |
周期性平滑动效(呼吸、摇摆、淡入淡出) |
_CosTime |
float4 |
(cos(t/8), cos(t/4), cos(t/2), cos(t)),t = 游戏运行总时间 |
与 _SinTime 配合实现相位偏移的周期动效 |
unity_DeltaTime |
float4 |
(dt, 1/dt, smoothDt, 1/smoothDt),其中 dt = 帧间隔时间 |
帧率无关的动效(避免动效速度随帧率变化) |
_AnimationTime |
float |
(Unity 2019+)动画时间(针对 SkinnedMeshRenderer),范围通常 0~1 | 顶点动画、骨骼动画联动的 Shader 效果 |
1. 最常用:_Time(线性时间)
_Time 是基础时间变量,四个分量对应不同速度的时间流逝,可直接用于线性动效:
_Time.x= 总时间 / 20 → 超慢速(适合缓慢位移、渐变)_Time.y= 总时间 → 常规速度(默认首选)_Time.z= 总时间 × 2 → 2 倍速_Time.w= 总时间 × 3 → 3 倍速
示例:UV 滚动(流光 / 流水效果)
// 片元着色器中实现纹理UV水平滚动
fixed4 frag (v2f i) : SV_Target
{
// 基础UV + 时间偏移(_Time.y是常规速度,乘以滚动速度系数_ScrollSpeed)
float2 uv = i.uv + float2(_ScrollSpeed * _Time.y, 0);
fixed4 col = tex2D(_MainTex, uv);
return col;
}
2. 周期动效:_SinTime / _CosTime(正弦 / 余弦时间)
正弦 / 余弦函数的取值范围是 [-1, 1],适合实现 "往复循环" 的动效(如呼吸、缩放、摇摆),通常会先映射到 [0, 1] 区间使用:
_SinTime.x= sin (t/8) → 周期 16π ≈ 50 秒(超慢呼吸)_SinTime.y= sin (t/4) → 周期 8π ≈ 25 秒_SinTime.z= sin (t/2) → 周期 4π ≈ 12 秒_SinTime.w= sin (t) → 周期 2π ≈ 6 秒
示例:呼吸灯效果(亮度随时间变化)
fixed4 frag (v2f i) : SV_Target
{
// 1. 获取正弦值(范围[-1,1])
float sinVal = _SinTime.w;
// 2. 映射到[0,1]区间(呼吸的亮度范围)
float brightness = (sinVal + 1.0) * 0.5;
// 3. 基础颜色 × 亮度(可叠加强度系数_BrightnessScale)
fixed4 col = tex2D(_MainTex, i.uv) * brightness * _BrightnessScale;
return col;
}
3. 帧率无关:unity_DeltaTime(帧时间)
直接用 _Time 可能因帧率波动导致动效速度不稳定,unity_DeltaTime 可实现帧率无关的动效:
unity_DeltaTime.x= 本次帧间隔时间(dt)unity_DeltaTime.y= 1/dt(慎用,帧率低时数值会很大)unity_DeltaTime.z= 平滑后的 dt(推荐,避免帧率突变)
示例:帧率无关的顶点位移
v2f vert (appdata v)
{
v2f o;
// 顶点基础位置 + 随时间的位移(乘以平滑帧时间,保证不同帧率下速度一致)
v.vertex.y += _MoveSpeed * unity_DeltaTime.z;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.uv;
return o;
}
溶解效果(时间驱动的 Alpha 裁剪)
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// 1. 噪声纹理(溶解边缘的随机效果)
fixed noise = tex2D(_NoiseTex, i.uv).r;
// 2. 时间驱动的溶解阈值(0~1,从无到有溶解)
float dissolveThreshold = _Time.y * _DissolveSpeed;
// 3. 裁剪像素(噪声值 < 阈值则透明)
clip(noise - dissolveThreshold);
// 4. 溶解边缘加红边
if (noise - dissolveThreshold < 0.1)
{ col.r = 1.0; }
return col;
}
避坑关键点
- 时间范围与映射 :
_SinTime/_CosTime的原始值是[-1,1],如需 0~1 的范围,用(val + 1.0) * 0.5映射;- 如需自定义周期,不要依赖内置的
_SinTime.x/y/z/w,而是自己计算:sin(_Time.y * _CustomSpeed)(_CustomSpeed是自定义速度系数)。
- 性能注意事项 :
- 避免在片元着色器中重复计算复杂的时间函数(如多次计算
sin(_Time.y)),可在顶点着色器中计算后插值传入; unity_DeltaTime.y(1/dt)在帧率极低时会趋近于无穷大,慎用,优先用unity_DeltaTime.z(平滑 dt)。
- 避免在片元着色器中重复计算复杂的时间函数(如多次计算
- 暂停处理 :
- Unity 的时间变量默认受
Time.timeScale影响(暂停时timeScale=0,时间停止); - 如需不受暂停影响的时间,用
_Time不如自己在 C# 中传Time.realtimeSinceStartup到 Shader(自定义 uniform 变量)。
- Unity 的时间变量默认受
使用包含文件简化Shader
核心功能是给模型渲染一张纹理贴图,并叠加自定义主颜色。

顶点着色器的作用:处理每个顶点的位置、纹理坐标等数据,传递给片元着色器。
v2f_img vert(appdata_img v):
appdata_img:UnityCG.cginc内置的顶点输入结构体 ,包含vertex(顶点位置)、texcoord(纹理坐标)等基础数据(无需自己定义结构体)。v2f_img:UnityCG.cginc内置的顶点输出 / 片元输入结构体 ,包含pos(裁剪空间位置)、uv(纹理坐标)。o.pos=UnityObjectToClipPos(v.vertex);:
UnityObjectToClipPos:Unity 内置宏(替代mul(UNITY_MATRIX_MVP, v.vertex)),将模型空间顶点 转换为裁剪空间顶点(显卡最终渲染的位置)。o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);:
TRANSFORM_TEX:UnityCG.cginc内置宏,计算纹理的最终 UV 坐标(叠加 Tiling/Offset),等价于:- o.uv = v.texcoord * _MainTex_ST.xy + _MainTex_ST.zw;
- 作用:让你在 Unity 面板调整纹理的 Tiling(缩放)和 Offset(偏移)时,UV 坐标同步变化。
片元着色器(frag 函数)
fixed4 frag(v2f_img i):SV_TARGET { return tex2D(_MainTex,i.uv)*_MainColor; }
片元着色器的作用:处理每个像素(片元)的颜色,是最终渲染效果的核心。
fixed4 frag(v2f_img i):SV_TARGET:
i:接收顶点着色器传递过来的v2f_img数据(包含pos和uv)。:SV_TARGET:声明函数返回值是渲染目标(即最终输出到屏幕的像素颜色)。tex2D(_MainTex,i.uv):采样纹理_MainTex在i.uv坐标处的颜色(tex2D是 2D 纹理采样函数)。*_MainColor:将采样得到的纹理颜色与主颜色相乘(叠加色调)。return:返回最终的像素颜色。