OpenGL内部只定义了: 裁剪空间、规范化设备空间、屏幕空间。
模型空间、世界空间、摄像机空间是为了方便用户而自定义的空间。
模型空间 -> 模型变换(M) -> 世界空间 -> 视变换(V) -> 摄像机空间 -> 投影变换( P ) -> 裁剪空间 -> 透视除法 -> 规范化设备空间(NDC) -> 屏幕映射 -> 屏幕空间
链接:模型、世界、观察、裁剪空间坐标转换
链接:unity 七种坐标系统详解与互相转换的方法
链接:矩阵与空间变换
连接:在Unity的后处理shader中通过屏幕像素坐标和深度贴图反推世界坐标
o.pos=mul(_unity_MVP, v.pos)
矩阵一般 用来表示一个点在子空间中的坐标为P子,其转换到父空间中的坐标为P父,则矩阵M定义了这种转换。
某矩阵可表示为:
Xc,Yc,Zc表示子空间的三个轴在父空间的方向,也表示子空间的三个单位方向轴的终点在父空间中的坐标。
Oc表示子空间的原点在父空间中的位置。
则子空间中的点在父空间中的表示:P父=M*P子。
Unity中的Transform组件变换为最终的矩阵。
两种顺序的理解:
如果以其它顺序,则会产生不正常的结果。参见:
矩阵相乘满足结合律:
((M1 X M2) X M3) X M~4` == M1 X (M2 X (M3 X M4)) == (M1 X M2) X (M3 X M4)
顺序不变,括号随便加。
从左往右乘:表示都是子空间(内含某点)沿自身空间轴变换。
从右向左乘:都是某点在父空间内变换。
某空间L内某点p绕L空间内某点o的旋转:p’ = To X R X (-To) X p
To为o点在L空间内的坐标。R为旋转的角度(也可以是一个纯旋转矩阵或者一个四元素)。
链接:unity shader中的矩阵变换知识
方向向量(Vx, Vy, Vz,0)乘以该矩阵,结果不变,表示向量无法位移。
点绕X轴旋转:(Px,PycosA-PzsingA, PysinA+pZcosA, 1),向量和点一致(w=0)
表示:点的X坐标不变,Y和Z坐标都变,而且都和YZ坐标有关。
从子空间理解:子空间的Y和Z轴向绕自身X轴旋转,那么子空间的Z轴转到父空间Y轴的下面去了,因此子空间的Z轴点在父空间中Y轴的负方向上。
(Px Sx, PysY, PzSz,1), (Vx Sx, VysY, VzSz,0),
一共有六种,如:Hxz, Hxy,…
Hxz:表示在xz平面内,沿着x轴进行切变。(Px+Pz*S, Py, Pz,1)
上图可表示,子空间的Z轴末端点在父空间的X轴上发生位移。
1:模型空间 ;2:世界空间; 3:观察空间; 4:裁剪空间(投影空间)
UNITY_MATRIX_MVP:将坐标或者方向从1到4
UNITY_MATRIX_MV:将坐标或者方向从1到3
UNITY_MATRIX_VP:将坐标或者方向从2到4
UNITY_MATRIX_V:将坐标或者方向从2到3
UNITY_MATRIX_P:将坐标或者方向从3到4
unity_ObjectToWorld:将顶点或者方向从1到2
unity_WorldToObject:unity_ObjectToWorld的逆矩阵,用于将顶点方向从2到1
UNITY_MATRIX_IT_MV:
UNITY_MATRIX_T_MV:
三者之间在Unity脚本内的坐标转换都要使用得到Camera组件。
//获取鼠标的屏幕系位置
var mousePos = Input.mousePosition; //此时mousePos.z为0
mousePos.z = 11.4; //必须要重新设置鼠标位置的z值。 表示当前离摄像机Z方向的距离(米)。
var viewportPos = Camera.main.ScreenToViewportPoint(mousePos); //此时viewportPos.z保持和mousePos.z相同。
var worldPos = Camera.main.ScreenToWorldPoint(mousePos); //此时worldPos.z表示:摄像机前方距离为mousePos.z的世界坐标。
//注意:如果mousePos.z设置为0 , 则worldPos始终为摄像机的世界坐标。
鼠标屏幕坐标转换为世界坐标的意义:相当于鼠标点在摄像机前方z距离的视口形状的平面内移动。
camera.ScreenToWorldPoint()内部应该是先转换到Viewport的坐标,再转换到世界坐标。
如果摄像机的视口没有填充整个屏幕,则以视口在屏幕内的形状为准。
//获取某物体的世界坐标
var worldPos = cube.Transform.position;
var viewportPos = Camera.main.WorldToViewportPoint(worldPos); //此时的viewportPos.z为该点距离摄像机Z方向的距离。
var screenPos = Camera.main.WorldToScreenPoint(worldPos); //此时的screenPos.z为该点距离摄像机Z方向的距离。
相关链接:
Unity中屏幕坐标、视口坐标和世界坐标、局部坐标与其之间的相互转换