本文记录一些Unity中可能用到的坐标变换的方法,包括在C#脚本中及在ShaderLab中:
CS脚本中
在C#脚本中会用到的坐标转换:
local(parent) -> world
本地坐标和世界坐标的转化,local实际上就是此对象的父节点空间,以下三行代码都会输出该GameObject
的世界坐标(有父节点的情况下):
1 | Debug.Log(transform.position); |
world -> local(parent)
将世界坐标转换为本地坐标,以下三行代码都会输出该GameObject
的本地坐标(有父节点的情况下):
1 | Debug.Log(transform.localPosition); |
如果需要计算某对象在另一个空间中的坐标,可通过local->world->someparent转换,也可以得出相对于父节点的变换矩阵,逐级变换:
逐级变换
假设现在有四个GameObject
对象,它们的分别被引用为t1
、t2
、t3
和t4
:
1 | public Transform t1; |
设置它们的父子关系如下:
1 | t4.SetParent(t3, false); |
使用m1
、m2
和m3
来保存t1
、t2
和t3
的变换矩阵(TRS),则可以看到下边的三个Debug.Log
都会输出t4
的世界坐标(t1
有父节点):
1 | Debug.Log(t4.position); |
将t4
连续的施以m3
、m2
和m1
,即可得到t4
在t1.parent
之下的局部坐标。
shader中
在顶点着色器中常常会使用一些变换,如下:
local -> world
本地坐标到世界坐标的转换,借助于内置变量unity_ObjectToWorld
,旧版本中叫做_Object2World
,将本地坐标pos
转换到为世界坐标的方法如下:
1 | mul(unity_ObjectToWorld, float4(pos, 1.0)); |
world -> local
世界坐标到本地坐标的转换,借助于内置变量unity_WorldToObject
,旧版本中叫做_World2Object
,将世界坐标pos
转换到为本地坐标的方法如下:
1 | mul(unity_WorldToObject, float4(pos, 1.0)); |
obj -> clip
最常用到的还是本地坐标到裁剪空间的坐标转换,如将本地坐标pos
转化为裁剪屏幕的坐标,可以调用第一行的函数,也可以使用第二行的矩阵乘法,Unity似乎会自动把mul(UNITY_MATRIX_MVP, *)
转化成前者:
1 | float4 UnityObjectToClipPos(float3 pos); |
REFERENCE
https://docs.unity3d.com/Manual/class-Transform.html
https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html