矩阵空间转换
矩阵几何概念
对于一个 向量,他的表现形式可以是 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表示矩阵