Unity Shader 的坐标空间转换(图解)
这篇小笔记主要是把 Unity Shader 里的坐标空间关系 用一张图梳理出来, 方便记忆模型空间、世界空间、观察空间、裁剪空间之间的转换, 以及对应的 Unity 内置矩阵与宏。
坐标空间关系概览
从模型导入到最终显示在屏幕上,顶点通常会经历以下几个空间:
- 模型空间(Model / Object / Local Space):模型自带的局部坐标系。
- 世界空间(World Space):把所有物体放到同一世界坐标系后的位置。
- 观察空间(View / Camera Space):以相机为原点、相机方向为轴的坐标系。
- 裁剪空间(Clip Space):应用投影矩阵后的空间,用于裁剪视锥体外的内容。
示意图大致如下:

最下方可以理解为「从模型空间一步步乘上 M、V、P 矩阵, 最后得到可以送去做裁剪和投影的裁剪空间坐标」。
常用矩阵与 Unity 内置宏
在 Unity 中,常用的几个矩阵含义可以简要整理如下:
- 模型到世界(M):
unity_ObjectToWorld/UNITY_MATRIX_M - 世界到观察(V):
unity_MatrixV/UNITY_MATRIX_V - 观察到裁剪(P):
glstate_matrix_projection/UNITY_MATRIX_P
组合之后就有:
- 模型到观察(M × V):
UNITY_MATRIX_MV或mul(unity_MatrixV, unity_ObjectToWorld) - 世界到裁剪(V × P):
UNITY_MATRIX_VP/unity_MatrixVP - 模型到裁剪(M × V × P,通常叫 MVP):
UNITY_MATRIX_MVP
下面按转换路径再拆一遍。
模型空间 → 世界空间(Model → World)
模型空间下的顶点位置 v.vertex,乘以模型变换矩阵即可得到世界空间坐标:
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
世界空间 → 观察空间(World → View)
把世界空间坐标乘以视图矩阵:
float4 viewPos = mul(unity_MatrixV, worldPos);
观察空间 → 裁剪空间(View → Clip)
再乘投影矩阵:
float4 clipPos = mul(UNITY_MATRIX_P, viewPos);
这一步会把视锥体变换到一个规则的立方体内,方便后续裁剪和归一化。
世界空间 → 裁剪空间(World → Clip)
如果你已经有世界空间坐标,也可以直接用 VP 矩阵:
float4 clipPos = mul(UNITY_MATRIX_VP, worldPos);
模型空间 → 观察空间(Model → View)
有时只需要到观察空间,而不是直接裁剪空间,可以使用 MV 矩阵:
float4 viewPos = mul(UNITY_MATRIX_MV, v.vertex);
// 或明确写出:V * M
float4 viewPos2 = mul(unity_MatrixV, mul(unity_ObjectToWorld, v.vertex));
模型空间 → 裁剪空间(Model → Clip / MVP)
最常见的完整路径就是「MVP 变换」:
float4 clipPos = mul(UNITY_MATRIX_MVP, v.vertex);
在 Unity 提供的辅助函数中,等价写法是:
o.pos = UnityObjectToClipPos(v.vertex);
这里 UnityObjectToClipPos 就是帮你把「对象空间顶点」
依次乘上 M、V、P 三个矩阵,得到可以直接用来输出到 SV_POSITION 的裁剪空间坐标。
顶点着色器中的典型用法
一个最基础的顶点着色器,一般至少会把输入的对象空间顶点转换到裁剪空间:
struct appdata
{
float4 vertex : POSITION;
// 其他属性:法线、UV 等
};
struct v2f
{
float4 pos : SV_POSITION;
// 其他插值数据
};
v2f vert (appdata v)
{
v2f o;
// 对象空间 → 裁剪空间
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
当你需要在世界空间做额外运算(比如基于世界坐标的光照、投影等),
就再额外计算一份 worldPos 并通过 v2f 传给片元着色器即可。
小结
- 记住四个主要空间:模型 → 世界 → 观察 → 裁剪;
- 熟悉 Unity 内置矩阵:
UNITY_MATRIX_M、UNITY_MATRIX_V、UNITY_MATRIX_P和组合形式MV、VP、MVP; - 在 Shader 里最常见的就是直接调用
UnityObjectToClipPos, 但理解背后做了什么,有助于你在需要世界空间或观察空间时写出更灵活的效果。
版权声明:本文最初发布于 CSDN「uniGame」,遵循 CC 4.0 BY-SA 协议,转载请附上原文链接及本声明。
原文链接:https://blog.csdn.net/alla_Candy/article/details/121176275