1、unity的坐标系
unity的世界坐标系是左手系;(左手系:握拳伸出左手,大拇指指向坐标轴正向、四指方向是旋转的正方向);unity的相机坐标系是右手系;unity的NDC(Normalized Device Coordinate归一化设备坐标)又是左手系。NDC由底层api决定,但每个硬件软件的api又都不太一样,unity为了兼容各种api,坐标系搞成了四不像。我们看一下DX、OpenGL、Vnlkan以及unity的坐标系对比:

emmmm,一言难尽....
unity的封装思路:是想在上层将各种坐标系包括UV坐标系抽象成OpenGL的规则,除了世界坐标系是左手系与OpenGL正好相反。
2、unity独一无二的:
- 欧拉角顺序:yxz
- 四元数顺序:xyzw;(一般标准都是wxyz)
3、untiy里的坐标系转换:
| CS脚本 | Shader |
| local->world |
| mul(unity_ObjectToWorld, float4(pos, 1.0)); |
| world->local |
| mul(unity_WorldToObject, float4(pos, 1.0)); |
| 逐级变换: 四个GM:t1 t2 t3 t4 public Transform t1;
public Transform t2;
public Transform t3;
public Transform t4; 设置父子关系: t4.SetParent(t3, false);
t3.SetParent(t2, false);
t2.SetParent(t1, false); t4.SetParent(t3, false); t3.SetParent(t2, false); t2.SetParent(t1, false); 使用m1 m2 m3来保存t1 t2 t3 的变换矩阵,求t4的世界坐标: 最简单的:Debug.Log(t4.position);
转换过程:
Matrix4x4 m1 = Matrix4x4.TRS(t1.localPosition, t1.localRotation, t1.localScale);
Matrix4x4 m2 = Matrix4x4.TRS(t2.localPosition, t2.localRotation, t2.localScale);
Matrix4x4 m3 = Matrix4x4.TRS(t3.localPosition, t3.localRotation, t3.localScale);
Debug.Log(t1.parent.localToWorldMatrix.MultiplyPoint(m1.MultiplyPoint(m2.MultiplyPoint(m3.MultiplyPoint(t4.localPosition)))));
Debug.Log((t1.parent.localToWorldMatrix * m1 * m2 * m3).MultiplyPoint(t4.localPosition)); | 将本地坐标pos转换为裁剪屏幕的坐标:
-
float4 UnityObjectToClipPos(float3 pos); -
mul(UNITY_MATRIX_MVP, float4(pos, 1.0));
|
附录:
Unity - Manual: Built-in shader variables
https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
Unity - Manual: Transforms
https://docs.unity3d.com/Manual/class-Transform.html
NDC手工转换:unity3d NDC 手工转换 - 知乎