TA学习之路——1.4 MVP矩阵运算
1.变换矩阵的意义
1.将3D物体转化到2D平面
2.为各个空间的运用做准备
2.MVP矩阵代表什么
MVP矩阵分别是模型(Model)、观察(View)、投影(Projecttion)三个矩阵。我们顶点坐标起始于局部空间(Local Space),在这里它称为局部坐标(Local Coordinate),它在之后会变为事件坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。
2.1 M矩阵
模型空间->世界空间
以自身为中心的空间坐标系
以世界为中心的空间坐标系
从模型空间变换到世界空间
1.第一步进行了缩放
2.第二步进行了旋转
3.第三步进行了平移
对应的依次进行矩阵变换得出变换矩阵
M
=
[
1
0
0
t
x
0
1
0
t
y
0
0
1
t
z
0
0
0
1
]
[
cos
θ
0
sin
θ
0
0
1
0
0
−
sin
θ
0
cos
θ
0
0
0
0
1
]
[
s
x
0
0
0
0
s
y
0
0
0
0
s
z
0
0
0
0
1
]
M= \begin{bmatrix} 1 & 0 & 0 & t_x\\ 0 & 1 & 0& t_y\\ 0 & 0 & 1 & t_z\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} \cos\theta & 0 & \sin\theta & 0\\ 0 & 1 & 0 & 0\\ -\sin\theta & 0 & \cos\theta & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} s_x & 0 & 0 & 0\\ 0 & s_y & 0 & 0\\ 0 & 0 & s_z & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}
M=
100001000010txtytz1
cosθ0−sinθ00100sinθ0cosθ00001
sx0000sy0000sz00001
模型空间下的顶点坐标乘M矩阵就可以得到世界空间下的顶点坐标
2.1 V矩阵
世界空间->视觉空间
以摄像机为中心(为零点)的空间坐标系
V矩阵是将世界空间变换到摄像机空间
平移整个观察空间,摄像机原点和世界坐标原点重合,坐标轴重合
摄像机是在世界空间中是先旋转,再平移
为了让摄像机与世界坐标重合,逆变换
1.第一步进行平移
2.第二步进行旋转
3.第三步Z分量取反(左手坐标系的原因)
对应的依次进行矩阵变换得出变换矩阵
将摄像机坐标系原点移动到世界坐标系原点
V = [ 1 0 0 0 0 cos θ − sin θ 0 0 sin θ cos θ 0 0 0 0 1 ] [ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] V= \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & \cos\theta & -\sin\theta& 0\\ 0 & \sin\theta & \cos\theta& 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & t_x\\ 0 & 1 & 0& t_y\\ 0 & 0 & 1 & t_z\\ 0 & 0 & 0 & 1 \end{bmatrix} V= 10000cosθsinθ00−sinθcosθ00001 100001000010txtytz1
2.2 P矩阵
视觉空间->裁剪空间
1.不是真正的投影,为投影做准备
2.目的:判断顶点是否在可见范围内。
3.P矩阵:对x,y,z分量进行缩放,用w分量做范围值。如果x,y,z都在w范围内,那么该点在裁剪空间内。
正交投影
通常同于2D游戏
透视投影
通常用于3D游戏
P
0
=
[
1
A
s
p
e
c
t
cot
F
O
V
2
0
0
0
0
cot
F
O
V
2
0
0
0
F
a
r
+
N
e
a
r
F
a
r
−
N
e
a
r
−
2
F
a
r
N
e
a
r
F
a
r
−
N
e
a
r
0
0
−
1
0
]
P_0=\begin{bmatrix} \frac {1} {Aspect}\cot \frac {FOV}{2} & 0 & 0 & 0 \\ 0 & \cot \frac {FOV}{2} & 0 \\ 0 & 0 & \frac {Far+Near} {Far-Near} & -\frac {2FarNear} {Far-Near}\\ 0 & 0 & -1 & 0 \end{bmatrix}
P0=
Aspect1cot2FOV0000cot2FOV0000Far−NearFar+Near−10−Far−Near2FarNear0
推导参考:https://blog.csdn.net/weixin_45724919/article/details/125368527?sharetype=blogdetail&sharerId=125368527&sharerefer=PC&sharesource=weixin_45724919&spm=1011.2480.3001.8118
shader控制代码
Shader "Unlit/NewUnlitShader 1"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
//_ADis("A Distance", Float) = 0.0 // 无范围限制
_ADis("A Distance", Range(0, 10)) = 1.0
_GDis("G Distance", Float) = 1.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0; // 绑定到纹理坐标
//UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION; //必须绑定到裁剪空间位置
float3 viewPos : TEXCOORD1;// 绑定到纹理坐标1
};
sampler2D _MainTex;
float4 _MainTex_ST;
// 必须在此处声明 ↓↓↓
float _ADis; // 保持与Properties中名称完全一致
float _GDis;
v2f vert (appdata v)
{
v2f o;
//UNITY_SETUP_INSTANCE_ID 是 Unity 着色器中用于 初始化当前实例 ID 的宏,
//主要服务于 GPU Instancing 技术。它的核心作用是通过设置全局变量 unity_InstanceID,
//使着色器能够正确访问当前渲染实例的唯一标识符。
UNITY_SETUP_INSTANCE_ID(v); // 必须位于着色器开头
//UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO 是 Unity URP(Universal Render Pipeline)中用于初始化立体渲染(Stereo Rendering)顶点输出数据的宏,
//主要解决 VR 或多目相机场景下左右眼视图的坐标变换问题。
//它会根据当前渲染的视角(左眼 / 右眼)自动调整顶点输出中的位置和视图参数
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);//必须在顶点着色器的最开始调用,否则可能导致后续坐标计算错误
//UnityObjectToClipPos(v.vertex) 是 Unity Shader 中的核心坐标变换函数,
//其作用为:将模型顶点从对象空间(Object Space)变换到裁剪空间(Clip Space)。
//这是所有顶点着色器必须执行的关键操作。
o.vertex = UnityObjectToClipPos(v.vertex);//mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, vertex))和MVP矩阵差不多
//TRANSFORM_TEX 是 Unity Shader 中的纹理坐标变换宏,
//其核心作用为:将原始UV坐标与材质属性的缩放(Tiling)和偏移(Offset)参数结合,生成最终采样用的UV坐标。
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
//UNITY_TRANSFER_FOG(o,o.vertex);
//UnityObjectToViewPos将顶点位置从模型空间转换到视图空间
o.viewPos = UnityObjectToViewPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//_ADis = 1;
//_GDis = 1;
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
//UNITY_APPLY_FOG(i.fogCoord, col);
//saturate是Shader编程中的关键数学函数,
//其功能是将输入值钳制(Clamp)到[0, 1]范围内,等价于 clamp(x, 0.0, 1.0),
//但在GPU上具有更高的执行效率。
float FadeAlpha = 1 - saturate((-i.viewPos.z - _ADis) / _GDis);
col *= FadeAlpha;
return col;
}
ENDCG
}
}
}
UnityShader参考地址
视频学习地址