参考[1][2],先说一下问题原因:代码里面传过来的近平面和远平面都是正数,但是在课程视频里面说的n, f都是负数,看范围也可以看出来是是要写成[f, n]。
看了一下参考[1][2]中一些同学说的方法,把正负取反,以及乘以一个变换矩阵,都觉得怪怪的,所以手动推导一遍投影矩阵,直接应用这个公式看看。
坐标系:右手坐标系

向量记法:列向量
V
=
(
x
y
z
1
)
V =
这个会导致空间中任意一个要归一化标准立方体的范围是[l,r]x[b,t]x[f,n]

简单思路就是,先把透视投影矩阵转换到正交投影矩阵
直接参考视频《Lecture 04 Transform Cont.》。先平移再缩放,这里因为是列向量表示法,所以是缩放矩阵x平移矩阵。
M
o
r
t
h
o
=
[
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
2
n
−
f
0
0
0
0
1
]
[
1
0
0
−
r
+
l
2
0
1
0
−
t
+
b
2
0
0
1
−
n
+
f
2
0
0
0
1
]
M_{ortho} =
对于3D空间中任意一点(x, y, z),其次坐标乘以任意一个非0的实数都表示的是3D空间中的同一个点。即(x, y, z, 1) == (xz, yz, z^2, z != 0),这里乘以特殊的z也是满足这个性质的。

可以很容易求出来(相似三角形)
y ′ = n z y y' = \dfrac{n}{z}y y′=zny

同理可得
x ′ = n z x x' = \dfrac{n}{z}x x′=znx
(
n
x
/
z
n
y
/
z
?
1
)
=
(
n
x
n
y
?
z
)
现在z不知道,接下来构建矩阵
M
p
e
r
s
p
−
>
o
r
t
h
o
(
x
y
z
1
)
=
(
n
x
/
z
n
y
/
z
?
z
)
=
(
n
x
n
y
?
z
)
M_{persp->ortho}
M
p
e
r
s
p
−
>
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
?
?
?
?
0
0
1
0
]
M_{persp->ortho} =
根据两个特例来求上面这个矩阵
(1)对于近平面上的点,变换前后没有任何变化
(2)对于远平面上的中心点,变换前后没有变换
近平面上的点满足条件
M
p
e
r
s
p
−
>
o
r
t
h
o
(
x
y
n
1
)
=
[
n
0
0
0
0
n
0
0
?
?
?
?
0
0
1
0
]
(
x
y
n
1
)
=
(
x
y
n
1
)
=
=
(
n
x
n
y
n
2
n
)
M_{persp->ortho}
可知第三行前面两个和xy无关,但是可能和后面两个有关,设为A和B。所以矩阵可以写成如下形式:
M
p
e
r
s
p
−
>
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
0
0
A
B
0
0
1
0
]
M_{persp->ortho} =
可得第一个等式
A n + B = n 2 An + B = n^2 An+B=n2
M
p
e
r
s
p
−
>
o
r
t
h
o
(
0
0
f
1
)
=
[
n
0
0
0
0
n
0
0
0
0
A
B
0
0
1
0
]
(
0
0
f
1
)
=
(
0
0
f
1
)
=
=
(
0
0
f
2
f
)
M_{persp->ortho}
可得第二个等式
A f + B = f 2 Af + B = f^2 Af+B=f2
根据两个等式可分别求得A和B:
A
=
n
+
f
B
=
−
n
f
因为f < n < 0,所以:
t
a
n
(
β
/
2
)
=
r
a
t
i
o
−
n
t
a
n
(
α
/
2
)
=
1
−
n
其中:
h
=
1
r
a
t
i
o
=
w
h
=
w
参考《3D Game Programming with DirectX 11》这本书里面的推导的概念,因为主要是关心纵横比(aspect ratio),所以可以简化的把h设置为1.
M
o
r
t
h
o
=
[
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
2
n
−
f
0
0
0
0
1
]
[
1
0
0
−
r
+
l
2
0
1
0
−
t
+
b
2
0
0
1
−
n
+
f
2
0
0
0
1
]
=
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
2
n
−
f
0
0
0
0
1
]
[
1
0
0
0
0
1
0
0
0
0
1
−
n
+
f
2
0
0
0
1
]
=
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
2
n
−
f
−
n
+
f
n
−
f
0
0
0
1
]
M
p
e
r
s
p
=
M
o
r
t
h
o
M
p
e
r
s
p
−
>
o
r
t
h
o
=
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
2
n
−
f
−
n
+
f
n
−
f
0
0
0
1
]
[
n
0
0
0
0
n
0
0
0
0
n
+
f
−
n
f
0
0
1
0
]
=
[
n
r
a
t
i
o
0
0
0
0
n
0
0
0
0
n
+
f
n
−
f
−
2
n
f
n
−
f
0
0
1
0
]
=
[
−
1
t
a
n
(
β
/
2
)
0
0
0
0
−
r
a
t
i
o
n
t
a
n
(
β
/
2
)
0
0
0
0
n
+
f
n
−
f
−
2
n
f
n
−
f
0
0
1
0
]
这样结果虽然对了,但是其实是不合理的,因为传进来的f > n > 0是和这个推导不一致的。如果把-f, -n 代入到上面的矩阵,结果还是不对。代码里面应该还有哪个地方做了一次转换把这个问题给屏蔽掉了,后面继续看!
关于推导,看到上面就ok了,但是我在想左手和右手坐标系关系到底有多大,所以打算推一遍左手坐标系的

V
=
(
x
,
y
,
z
,
1
)
V =
注意这里f > n > 0
M
o
r
t
h
o
=
[
1
0
0
0
0
1
0
0
0
0
1
0
−
r
+
l
2
−
t
+
b
2
−
n
+
f
2
1
]
[
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
2
f
−
n
0
0
0
0
1
]
=
[
1
0
0
0
0
1
0
0
0
0
1
0
0
0
−
n
+
f
2
1
]
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
2
f
−
n
0
0
0
0
1
]
=
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
2
f
−
n
0
0
0
−
n
+
f
f
−
n
1
]
求出来的A和B跟右手坐标系是一样的结果:
A
=
n
+
f
B
=
−
n
f
从这里可以看出来一点就是透视到正交的变换是跟坐标系无关的
M
p
e
r
s
p
=
M
p
e
r
s
p
−
>
o
r
t
h
o
M
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
0
0
n
+
f
−
n
f
0
0
1
0
]
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
2
f
−
n
0
0
0
−
n
+
f
f
−
n
1
]
=
[
n
r
a
t
i
o
0
0
0
0
n
0
0
0
0
n
+
f
f
−
n
1
0
0
2
n
f
f
−
n
0
]
=
[
1
t
a
n
(
β
/
2
)
0
0
0
0
r
a
t
i
o
n
t
a
n
(
β
/
2
)
0
0
0
0
n
+
f
f
−
n
1
0
0
2
n
f
f
−
n
0
]
可以看到这里和《3D数学基础图形与游戏开发》这本书上的是一样的

书上推导出来的矩阵形式如下:
[
1
r
t
a
n
(
α
/
2
)
0
0
0
0
1
t
a
n
(
α
/
2
)
0
0
0
0
f
f
−
n
1
0
0
−
n
f
f
−
n
0
]
参考书上5.6.3.4章节
原因主要是DX里面要求的立方体在z轴方向的范围是[0,1],而不是这里的[-1,1]。所以,把上面的正交投影矩阵改一下即可
M
o
r
t
h
o
=
[
1
0
0
0
0
1
0
0
0
0
1
0
−
r
+
l
2
−
t
+
b
2
−
n
1
]
[
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
1
f
−
n
0
0
0
0
1
]
=
[
1
0
0
0
0
1
0
0
0
0
1
0
0
0
−
n
1
]
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
1
f
−
n
0
0
0
0
1
]
=
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
1
f
−
n
0
0
0
−
n
f
−
n
1
]
M
p
e
r
s
p
=
M
p
e
r
s
p
−
>
o
r
t
h
o
M
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
0
0
n
+
f
−
n
f
0
0
1
0
]
[
1
r
a
t
i
o
0
0
0
0
1
0
0
0
0
1
f
−
n
0
0
0
−
n
f
−
n
1
]
=
[
1
t
a
n
(
β
/
2
)
0
0
0
0
r
a
t
i
o
n
t
a
n
(
β
/
2
)
0
0
0
0
f
f
−
n
1
0
0
−
n
f
f
−
n
0
]
这样就和书上一致了。
[1]https://zhuanlan.zhihu.com/p/509902950
[2]https://games-cn.org/forums/forum/graphics-intro/page/3/
[3]https://www.bilibili.com/video/BV1X7411F744?p=4&vd_source=c10ae5c27bbde8ef3af23889645a0d8b
[4]《3D Game Programming with DirectX 11》
[5]《3D数学基础图形与游戏开发》