常用
最常用的函数
| 排名 | 函数 | 用途 | 频率 |
| 1 | UnityObjectToClipPos | 顶点变换 | ⭐⭐⭐⭐⭐ |
| 2 | UnityObjectToWorldNormal | 法线变换 | ⭐⭐⭐⭐⭐ |
| 3 | UnityObjectToWorldDIr | 切线变换 | ⭐⭐⭐⭐⭐ |
| 4 | normalize | 向量归一化 | ⭐⭐⭐⭐⭐ |
| 5 | dot | 点积(光照) | ⭐⭐⭐⭐⭐ |
| 6 | tex2D | 纹理采样 | ⭐⭐⭐⭐⭐ |
| 7 | UnityWorldSpaceLightDir | 光照方向 | ⭐⭐⭐⭐ |
| 8 | UnityWorldSpaceViewDir | 视线方向 | ⭐⭐⭐⭐ |
| 9 | mul(unity_ObjectToWorld, v.vertex) | 世界坐标 | ⭐⭐⭐⭐ |
| 10 | lerp | 插值混合 | ⭐⭐⭐⭐ |
| 11 | saturate | 限制[0,1] | ⭐⭐⭐ |
| 12 | TRANSFORM_TEX(v.texcoord, _MainTex) | UV控制 | ⭐⭐⭐⭐⭐ |
| 13 | clip(); | 裁剪 | ⭐⭐⭐⭐ |
最常用的5个矩阵
| 排名 | 矩阵 | 变换 | 频率 |
| 1 | unity_ObjectToWorld | 模型→世界 | ⭐⭐⭐⭐⭐ |
| 2 | UNITY_MATRIX_MVP | 模型→裁剪 | ⭐⭐⭐⭐ |
| 3 | UNITY_MATRIX_V | 世界→视图 | ⭐⭐⭐ |
| 4 | UNITY_MATRIX_P | 视图→裁剪 | ⭐⭐⭐ |
| 5 | UNITY_MATRIX_VP | 世界→裁剪 | ⭐⭐⭐ |
全部
一、Unity坐标空间变换函数总表
位置变换函数
| 函数名 | 输入 | 输出 | 说明 | 示例 |
| UnityObjectToClipPos | 模型空间位置 | 裁剪空间位置 | 最常用,模型→裁剪 | float4 clipPos = UnityObjectToClipPos(v.vertex); |
| UnityObjectToViewPos | 模型空间位置 | 视图空间位置 | 模型→视图 | float3 viewPos = UnityObjectToViewPos(v.vertex); |
| UnityWorldToViewPos | 世界空间位置 | 视图空间位置 | 世界→视图 | float3 viewPos = UnityWorldToViewPos(worldPos); |
| UnityWorldToClipPos | 世界空间位置 | 裁剪空间位置 | 世界→裁剪 | float4 clipPos = UnityWorldToClipPos(worldPos); |
| mul(unity_ObjectToWorld, v.vertex) | 模型空间位置 | 世界空间位置 | 模型→世界(手动) | float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; |
方向/法线变换函数
| 函数名 | 输入 | 输出 | 说明 | 示例 |
| UnityObjectToWorldNormal | 模型空间法线 | 世界空间法线 | 自动处理转置逆 | float3 worldNormal = UnityObjectToWorldNormal(v.normal); |
| UnityObjectToWorldDir | 模型空间方向 | 世界空间方向 | 方向向量变换 | float3 worldDir = UnityObjectToWorldDir(v.tangent.xyz); |
| UnityWorldToObjectDir | 世界空间方向 | 模型空间方向 | 反向变换 | float3 objDir = UnityWorldToObjectDir(lightDir); |
光照相关函数
| 函数名 | 输入 | 输出 | 说明 | 示例 |
| UnityWorldSpaceLightDir | 世界空间位置 | 光源方向(世界空间) | 自动处理点光源/方向光 | float3 lightDir = UnityWorldSpaceLightDir(worldPos); |
| ObjSpaceLightDir | 模型空间位置 | 光源方向(模型空间) | 模型空间光照 | float3 lightDir = ObjSpaceLightDir(v.vertex); |
| UnityWorldSpaceViewDir | 世界空间位置 | 视线方向(世界空间) | 从顶点指向相机 | float3 viewDir = UnityWorldSpaceViewDir(worldPos); |
| ObjSpaceViewDir | 模型空间位置 | 视线方向(模型空间) | 模型空间视线 | float3 viewDir = ObjSpaceViewDir(v.vertex); |
屏幕空间相关函数
| 函数名 | 输入 | 输出 | 说明 | 示例 |
| ComputeScreenPos | 裁剪空间位置 | 屏幕空间位置 | 用于屏幕特效 | float4 screenPos = ComputeScreenPos(clipPos); |
| ComputeGrabScreenPos | 裁剪空间位置 | 抓取屏幕位置 | 用于折射等效果 | float4 grabPos = ComputeGrabScreenPos(clipPos); |
深度相关函数
| 函数名 | 输入 | 输出 | 说明 | 示例 |
| COMPUTE_EYEDEPTH | SV_POSITION | 线性眼空间深度 | 计算深度值 | COMPUTE_EYEDEPTH(o.depth); |
| DECODE_EYEDEPTH | 深度纹理值 | 线性眼空间深度 | 解码深度 | float depth = DECODE_EYEDEPTH(depthTex); |
| Linear01Depth | 深度缓冲值 | [0,1]线性深度 | 深度值线性化 | float depth = Linear01Depth(depthValue); |
| LinearEyeDepth | 深度缓冲值 | 眼空间线性深度 | 实际距离 | float depth = LinearEyeDepth(depthValue); |
二、Unity变换矩阵总表
基础变换矩阵
| 矩阵名 | 类型 | 变换 | 说明 | 使用示例 |
| unity_ObjectToWorld | float4x4 | 模型→世界 | M矩阵 | float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; |
| unity_WorldToObject | float4x4 | 世界→模型 | M逆矩阵 | float3 objPos = mul(unity_WorldToObject, worldPos).xyz; |
| UNITY_MATRIX_V | float4x4 | 世界→视图 | V矩阵(视图矩阵) | float3 viewPos = mul(UNITY_MATRIX_V, worldPos).xyz; |
| UNITY_MATRIX_I_V | float4x4 | 视图→世界 | V逆矩阵 | float3 worldPos = mul(UNITY_MATRIX_I_V, viewPos).xyz; |
| UNITY_MATRIX_P | float4x4 | 视图→裁剪 | P矩阵(投影矩阵) | float4 clipPos = mul(UNITY_MATRIX_P, viewPos); |
组合变换矩阵
| 矩阵名 | 类型 | 变换 | 等价于 | 使用示例 |
| UNITY_MATRIX_VP | float4x4 | 世界→裁剪 | P × V | float4 clipPos = mul(UNITY_MATRIX_VP, worldPos); |
| UNITY_MATRIX_MVP | float4x4 | 模型→裁剪 | P × V × M | float4 clipPos = mul(UNITY_MATRIX_MVP, v.vertex); |
| UNITY_MATRIX_MV | float4x4 | 模型→视图 | V × M | float3 viewPos = mul(UNITY_MATRIX_MV, v.vertex).xyz; |
| UNITY_MATRIX_IT_MV | float4x4 | 法线变换(模型→视图) | (MV)^-T(转置逆) | float3 viewNormal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal); |
特殊矩阵
| 矩阵名 | 类型 | 说明 | 使用场景 |
| unity_MatrixInvP | float4x4 | 投影矩阵的逆 | 深度重建世界坐标 |
| unity_MatrixInvVP | float4x4 | VP矩阵的逆 | 屏幕坐标→世界坐标 |
| unity_WorldToCamera | float4x4 | 世界→相机矩阵 | 等同于UNITY_MATRIX_V |
| unity_CameraToWorld | float4x4 | 相机→世界矩阵 | 等同于UNITY_MATRIX_I_V |
三、空间变换流程对照表
完整变换链
| 空间 | 坐标范围 | 如何到达 | 常用矩阵/函数 | 用途 |
| 模型空间 | 物体局部坐标 | 从Mesh读取 | v.vertex | 顶点动画、物体局部效果 |
| ↓ | | M矩阵 | unity_ObjectToWorld | |
| 世界空间 | 场景全局坐标 | mul(unity_ObjectToWorld, v.vertex) | UnityObjectToWorldNormal | 光照计算、物体交互 |
| ↓ | | V矩阵 | UNITY_MATRIX_V | |
| 视图空间 | 相机为原点 | mul(UNITY_MATRIX_V, worldPos) | UnityWorldToViewPos | 雾效、深度计算 |
| ↓ | | P矩阵 | UNITY_MATRIX_P | |
| 裁剪空间 | (x,y,z,w) | UnityObjectToClipPos(v.vertex) | UNITY_MATRIX_MVP | 输出到SV_POSITION |
| ↓ | | 透视除法 | 硬件自动 | |
| NDC空间 | [-1,1]或[0,1] | /w(硬件) | - | 归一化坐标 |
| ↓ | | 视口变换 | 硬件自动 | |
| 屏幕空间 | 像素坐标 | ComputeScreenPos | - | 屏幕特效、UI |
四、常用变换组合速查表
位置变换快速查询
| 从 → 到 | 方法1(函数) | 方法2(矩阵) | 推荐 |
| 模型 → 世界 | - | mul(unity_ObjectToWorld, v.vertex).xyz | 矩阵 |
| 模型 → 视图 | UnityObjectToViewPos(v.vertex) | mul(UNITY_MATRIX_MV, v.vertex).xyz | 函数 |
| 模型 → 裁剪 | UnityObjectToClipPos(v.vertex) | mul(UNITY_MATRIX_MVP, v.vertex) | 函数⭐ |
| 世界 → 视图 | UnityWorldToViewPos(worldPos) | mul(UNITY_MATRIX_V, float4(worldPos, 1)).xyz | 函数 |
| 世界 → 裁剪 | UnityWorldToClipPos(worldPos) | mul(UNITY_MATRIX_VP, float4(worldPos, 1)) | 函数 |
| 视图 → 裁剪 | - | mul(UNITY_MATRIX_P, float4(viewPos, 1)) | 矩阵 |
法线/方向变换快速查询
| 从 → 到 | 方法1(函数) | 方法2(矩阵) | 推荐 | 注意事项 |
| 模型法线 → 世界 | UnityObjectToWorldNormal(v.normal) | mul((float3x3)unity_WorldToObject, v.normal) | 函数⭐ | 自动转置逆 |
| 模型方向 → 世界 | UnityObjectToWorldDir(v.tangent.xyz) | mul((float3x3)unity_ObjectToWorld, dir) | 函数 | 不需要转置逆 |
| 世界方向 → 模型 | UnityWorldToObjectDir(worldDir) | mul((float3x3)unity_WorldToObject, dir) | 函数 | - |
五、光照计算常用函数表
光照方向获取
| 函数 | 输入空间 | 输出 | 光源类型支持 | 说明 |
| UnityWorldSpaceLightDir(worldPos) | 世界空间位置 | 世界空间光源方向 | 方向光、点光源、聚光灯 | 自动处理衰减 |
| ObjSpaceLightDir(v.vertex) | 模型空间位置 | 模型空间光源方向 | 方向光、点光源、聚光灯 | 模型空间光照 |
| _WorldSpaceLightPos0 | - | 世界空间光源位置/方向 | 主光源 | 方向光时为方向向量 |
视线方向获取
| 函数 | 输入空间 | 输出 | 说明 |
| UnityWorldSpaceViewDir(worldPos) | 世界空间位置 | 世界空间视线方向 | 从顶点指向相机 |
| ObjSpaceViewDir(v.vertex) | 模型空间位置 | 模型空间视线方向 | 模型空间视线 |
| _WorldSpaceCameraPos | - | 世界空间相机位置 | 相机位置 |
光照颜色/属性
| 变量名 | 类型 | 说明 | 使用场景 |
| _LightColor0 | fixed4 | 主光源颜色 | 前向渲染 |
| UNITY_LIGHTMODEL_AMBIENT | fixed4 | 环境光颜色 | 所有管线 |
| unity_SHAr, unity_SHAg, unity_SHAb | float4 | 球谐光照 | 间接光照 |
六、纹理采样相关函数表
基础采样函数
| 函数 | 说明 | Shader Model要求 | 示例 |
| tex2D(sampler, uv) | 2D纹理采样 | 2.0+ | fixed4 col = tex2D(_MainTex, i.uv); |
| tex2Dlod(sampler, float4(uv, 0, mip)) | 指定mipmap层级 | 3.0+ | fixed4 col = tex2Dlod(_MainTex, float4(i.uv, 0, 0)); |
| tex2Dproj(sampler, float4) | 投影纹理采样 | 2.0+ | fixed4 col = tex2Dproj(_MainTex, screenPos); |
| tex2Dbias(sampler, float4(uv, 0, bias)) | 带偏移的采样 | 2.0+ | fixed4 col = tex2Dbias(_MainTex, float4(i.uv, 0, -1)); |
纹理采样(URP/HDRP)
| 函数 | 说明 | 示例 |
| SAMPLE_TEXTURE2D(tex, sampler, uv) | URP/HDRP标准采样 | SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); |
| SAMPLE_TEXTURE2D_LOD(tex, sampler, uv, lod) | 指定LOD | SAMPLE_TEXTURE2D_LOD(_MainTex, sampler_MainTex, i.uv, 0); |
| SAMPLE_DEPTH_TEXTURE(tex, sampler, uv) | 深度纹理采样 | SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, i.uv); |
衍生指令(需要3.0+)
| 函数 | 说明 | 用途 | 示例 |
| ddx(x) | x对屏幕X的偏导 | 计算变化率 | float dUdx = ddx(i.uv.x); |
| ddy(y) | y对屏幕Y的偏导 | 计算变化率 | float dUdy = ddy(i.uv.y); |
| fwidth(x) | abs(ddx(x)) + abs(ddy(x)) | 边缘检测 | float edge = fwidth(i.uv); |
七、数学函数速查表
常用数学函数
| 函数 | 说明 | 范围 | 示例 |
| dot(a, b) | 点积 | [-1, 1](归一化向量) | float ndotl = dot(normal, lightDir); |
| cross(a, b) | 叉积 | 垂直向量 | float3 binormal = cross(normal, tangent); |
| normalize(v) | 归一化 | 长度=1 | float3 normal = normalize(i.worldNormal); |
| length(v) | 向量长度 | >= 0 | float dist = length(worldPos - _WorldSpaceCameraPos); |
| distance(a, b) | 两点距离 | >= 0 | float dist = distance(worldPos, lightPos); |
| reflect(i, n) | 反射向量 | - | float3 reflectDir = reflect(-viewDir, normal); |
| refract(i, n, eta) | 折射向量 | - | float3 refractDir = refract(-viewDir, normal, 1.0/1.33); |
| lerp(a, b, t) | 线性插值 | - | fixed3 color = lerp(shadowColor, litColor, ndotl); |
| smoothstep(min, max, x) | 平滑插值 | [0, 1] | float smooth = smoothstep(0.4, 0.6, ndotl); |
| step(edge, x) | 阶梯函数 | 0或1 | float toon = step(0.5, ndotl); |
| saturate(x) | 限制到[0,1] | [0, 1] | float val = saturate(ndotl); |
| clamp(x, min, max) | 限制范围 | [min, max] | float val = clamp(ndotl, 0.2, 0.8); |
| pow(x, y) | x的y次方 | - | float spec = pow(ndoth, _Gloss); |
| exp(x) | e^x | - | float fog = exp(-depth * density); |
| log(x) | ln(x) | - | - |
| sqrt(x) | 平方根 | - | float dist = sqrt(x*x + y*y); |
| abs(x) | 绝对值 | >= 0 | float val = abs(x); |
| sign(x) | 符号 | -1, 0, 1 | float s = sign(x); |
| floor(x) | 向下取整 | - | float stepped = floor(x * 5) / 5; |
| ceil(x) | 向上取整 | - | float stepped = ceil(x * 5) / 5; |
| frac(x) | 小数部分 | [0, 1) | float f = frac(x); |
| fmod(x, y) | x % y | - | float m = fmod(x, 2.0); |
三角函数
| 函数 | 说明 | 输入单位 | 范围 |
| sin(x) | 正弦 | 弧度 | [-1, 1] |
| cos(x) | 余弦 | 弧度 | [-1, 1] |
| tan(x) | 正切 | 弧度 | (-∞, +∞) |
| asin(x) | 反正弦 | - | [-π/2, π/2] |
| acos(x) | 反余弦 | - | [0, π] |
| atan(x) | 反正切 | - | [-π/2, π/2] |
| atan2(y, x) | 两参数反正切 | - | [-π, π] |
八、语义(Semantics)速查表
顶点着色器输入语义
| 语义 | 类型 | 说明 | 来源 |
| POSITION | float4 | 顶点位置(模型空间) | Mesh |
| NORMAL | float3 | 法线(模型空间) | Mesh |
| TANGENT | float4 | 切线(模型空间,w=±1) | Mesh |
| TEXCOORD0-7 | float2/4 | UV坐标 | Mesh |
| COLOR | fixed4 | 顶点颜色 | Mesh |
| SV_VertexID | uint | 顶点索引 | 系统自动 |
| SV_InstanceID | uint | 实例索引(GPU Instancing) | 系统自动 |
顶点着色器输出/片元着色器输入语义
| 语义 | 类型 | 说明 | 必须 |
| SV_POSITION | float4 | 裁剪空间位置 | ✅必须 |
| TEXCOORD0-9 | float1-4 | 任意插值数据 | 可选 |
| COLOR0-1 | fixed4 | 颜色数据 | 可选 |
| SV_IsFrontFace | bool | 是否正面(片元输入) | 可选 |
完整的顶点输入语义列表:
| 语义 | 含义 | 数据类型 |
POSITION | 顶点位置(模型空间) | float4 |
NORMAL | 法线(模型空间) | float3 |
TANGENT | 切线(模型空间) | float4 |
TEXCOORD0 | 第一套UV | float2/float4 |
TEXCOORD1 | 第二套UV(光照贴图) | float2/float4 |
TEXCOORD2 | 第三套UV | float2/float4 |
TEXCOORD3 | 第四套UV | float2/float4 |
COLOR | 顶点颜色 | float4 |
SV_VertexID | 顶点ID | uint |
SV_InstanceID | 实例ID(GPU Instancing) | uint |
片元着色器输出语义
| 语义 | 类型 | 说明 | 用途 |
| SV_Target | fixed4 | 渲染目标0 | 输出颜色(单目标) |
| SV_Target0-7 | fixed4 | 渲染目标0-7 | MRT(多目标) |
| SV_Depth | float | 自定义深度 | 深度输出 |
常用系统值语义
| 语义 | 使用位置 | 含义 |
SV_POSITION | 顶点输出 | 裁剪空间位置 |
SV_Target | 片元输出 | 渲染目标 |
SV_Depth | 片元输出 | 深度值 |
SV_VertexID | 顶点输入 | 顶点索引 |
SV_InstanceID | 顶点输入 | 实例索引 |
SV_PrimitiveID | 几何/片元输入 | 图元ID |
SV_IsFrontFace | 片元输入 | 是否正面 |
SV_RenderTargetArrayIndex | 几何输出 | 渲染目标数组索引 |
示例1:SV_VertexID(顶点ID)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| struct appdata
{
float4 vertex : POSITION;
uint vertexID : SV_VertexID; // 顶点索引
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
// 使用顶点ID生成渐变色
float t = (float)v.vertexID / 100.0;
o.color = float4(t, 1-t, 0, 1);
return o;
}
|
示例2:SV_IsFrontFace(正反面检测)
1
2
3
4
5
6
7
8
| fixed4 frag(v2f i, bool isFrontFace : SV_IsFrontFace) : SV_Target
{
// 正面显示红色,背面显示蓝色
if (isFrontFace)
return fixed4(1, 0, 0, 1); // 红色
else
return fixed4(0, 0, 1, 1); // 蓝色
}
|
示例3:SV_PrimitiveID(三角形ID)
1
2
3
4
5
6
| fixed4 frag(v2f i, uint primitiveID : SV_PrimitiveID) : SV_Target
{
// 每个三角形不同颜色
float hue = frac((float)primitiveID * 0.618);
return fixed4(hue, 1-hue, 0.5, 1);
}
|
示例4:SV_Depth(自定义深度)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| struct fragOutput
{
fixed4 color : SV_Target;
float depth : SV_Depth;
};
fragOutput frag(v2f i)
{
fragOutput o;
o.color = tex2D(_MainTex, i.uv);
// 强制深度为0.5(总在中间)
o.depth = 0.5;
return o;
}
|
九、渲染状态关键字表
剔除模式
| 关键字 | 说明 |
| Cull Back | 剔除背面(默认) |
| Cull Front | 剔除正面 |
| Cull Off | 双面渲染 |
深度测试
| 关键字 | 说明 |
| ZTest Less | 深度小于通过(默认) |
| ZTest LEqual | 深度小于等于通过 |
| ZTest Greater | 深度大于通过 |
| ZTest GEqual | 深度大于等于通过 |
| ZTest Equal | 深度等于通过 |
| ZTest NotEqual | 深度不等于通过 |
| ZTest Always | 总是通过 |
| ZTest Never | 总不通过 |
深度写入
| 关键字 | 说明 |
| ZWrite On | 写入深度(默认) |
| ZWrite Off | 不写入深度(透明物体) |
混合模式
| 关键字 | 效果 | 用途 |
| Blend Off | 无混合(默认) | 不透明物体 |
| Blend SrcAlpha OneMinusSrcAlpha | 标准透明 | 透明物体 |
| Blend One One | 加法混合 | 发光、粒子 |
| Blend OneMinusDstColor One | 柔和叠加 | 特效 |
| Blend DstColor Zero | 乘法混合 | 阴影、滤镜 |
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
| Shader "Tutorial/CompleteReference"
{
Properties
{
_MainTex ("Albedo", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags { "LightMode"="ForwardBase" }
Cull Back // 剔除背面
ZWrite On // 写入深度
ZTest LEqual // 深度测试
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma target 3.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
// ===========================================
// 顶点着色器输入
// ===========================================
struct appdata
{
float4 vertex : POSITION; // 模型空间位置
float3 normal : NORMAL; // 模型空间法线
float4 tangent : TANGENT; // 模型空间切线
float2 uv : TEXCOORD0; // UV0
float2 uv2 : TEXCOORD1; // UV1(光照贴图)
fixed4 color : COLOR; // 顶点颜色
};
// ===========================================
// 顶点到片元
// ===========================================
struct v2f
{
float4 pos : SV_POSITION; // 裁剪空间位置(必须)
float2 uv : TEXCOORD0; // UV
float3 worldPos : TEXCOORD1; // 世界空间位置
float3 worldNormal : TEXCOORD2; // 世界空间法线
float3 worldTangent : TEXCOORD3; // 世界空间切线
float3 worldBinormal : TEXCOORD4; // 世界空间副法线
};
// ===========================================
// 顶点着色器
// ===========================================
v2f vert(appdata v)
{
v2f o;
// 位置变换
o.pos = UnityObjectToClipPos(v.vertex); // 模型→裁剪
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; // 模型→世界
// 法线变换
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
o.worldBinormal = cross(o.worldNormal, o.worldTangent) * v.tangent.w;
// UV变换
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
// ===========================================
// 片元着色器
// ===========================================
fixed4 frag(v2f i) : SV_Target
{
// 归一化插值后的向量
float3 worldNormal = normalize(i.worldNormal);
// 光照方向(世界空间)
float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
// 视线方向(世界空间)
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
// 漫反射
float ndotl = max(0, dot(worldNormal, worldLightDir));
// 采样纹理
fixed4 albedo = tex2D(_MainTex, i.uv) * _Color;
// 最终颜色
fixed3 diffuse = _LightColor0.rgb * albedo.rgb * ndotl;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo.rgb;
return fixed4(ambient + diffuse, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
|