矩阵空间转换

矩阵几何概念

对于一个 向量,他的表现形式可以是 x向量 + y向量,也可以是 单位向量的缩放 用矩阵的方式表示

不同空间 值的转换

世界空间转观察空间

code
//世界空间转观察空间 //公式 P_view = [W_view] * P_world == P_view = [V_World]^-1 * P_world == P_view = [V_World]^T * P_world float3 viewZ = normalize(_ViewPos - _ViewTarget); float3 viewY = float3(0,1,0); float3 viewX = cross(viewZ,viewY); viewY = cross(viewX,viewZ);
float4x4 W2VMatrix = float4x4( viewX.x,viewX.y,viewX.z,0, viewY.x,viewY.y,viewY.z,0, viewZ.x,viewZ.y,viewZ.z,0, 0,0,0,1 ); float4x4 W2VTransformMatrix = float4x4( 1,0,0,-_ViewPos.x, 0,1,0,-_ViewPos.y, 0,0,1,-_ViewPos.z, 0,0,0,1 ); float4x4 ToViewMatrix = mul(W2VMatrix,W2VTransformMatrix);
float3 positionWS = TransformObjectToWorld(v.posOS); float3 positionVS = mul(ToViewMatrix,float4(positionWS,1)); o.posCS = TransformWViewToHClip(positionVS);

观察空间转裁剪空间

正交相机
观察空间与裁剪空间 很相似,他们的 x y 轴都是一样的,z 轴相反(观察空间是右手坐标系,裁剪空间是左手坐标系)
而观察空间之所以要与裁剪空间 转换,是因为 裁剪空间的大小是有限制的空间
x轴推导
y轴推导
z轴推导
通过推导组成的矩阵
因为再DX平台z值要反转(0-1 转为 1-0)所以再DX平台的矩阵为
code
//观察空间 转 裁剪空间 float h = _CameraParams.x * 2; //裁剪空间 高 float r = _CameraParams.w; //裁剪空间 宽高比 float w = h * r; //裁剪空间 宽 float n = _CameraParams.y; // 裁剪空间 近裁剪面值 float f = _CameraParams.z; // 裁剪空间 远裁剪面值 //P_clip = [V_clip] * P_view float4x4 V2CMatrix; if (UNITY_NEAR_CLIP_VALUE == -1) { //OpenGl (-1,1) V2CMatrix = float4x4( 2 / w, 0, 0, 0, 0, 2 / h, 0, 0, 0, 0, 2 / (n - f), (n + f) / (n - f), 0, 0, 0, 1 ); } if (UNITY_NEAR_CLIP_VALUE == 1) { //DX (0,1) V2CMatrix = float4x4( 2 / w, 0, 0, 0, 0, -2 / h, 0, 0, 0, 0, 1 / (f - n), f / (f - n), 0, 0, 0, 1 ); } // o.posCS = TransformWViewToHClip(positionVS); o.posCS = mul(V2CMatrix, float4(positionVS, 1));
齐次坐标
(1,2,3)的齐次坐标 加一维向量w 保证(x/w,y/w,z/w,w) == 原坐标
透视相机
观察空间 转换到 齐次裁剪空间的矩阵
code
//观察空间 转 裁剪空间 float h = _CameraParams.x * 2; //裁剪空间 高 float r = _CameraParams.w; //裁剪空间 宽高比 float w = h * r; //裁剪空间 宽 float n = _CameraParams.y; // 裁剪空间 近裁剪面值 float f = _CameraParams.z; // 裁剪空间 远裁剪面值
//透视矩阵 float4x4 V2CMatrixPerspective;
if (UNITY_NEAR_CLIP_VALUE == -1) { //OpenGL V2CMatrixPerspective = float4x4 ( 2 * n / w, 0, 0, 0, 0, 2 * n / h, 0, 0, 0, 0, (n + f) / (n - f), (2 * n * f) / (n - f), 0, 0, -1, 0 ); } if (UNITY_NEAR_CLIP_VALUE == 1) { //DX V2CMatrixPerspective = float4x4 ( 2 * n / w, 0, 0, 0, 0, -2 * n / h, 0, 0, 0, 0, n / (f - n), n * f / (f - n), 0, 0, -1, 0 ); } // o.posCS = TransformWViewToHClip(positionVS); o.posCS = mul(V2CMatrixPerspective, float4(positionVS, 1));
通过FOV表示矩阵