注意,以下求法的原理不再赘述。最简单的求法请直接跳转文末总结。
文章目录
概述
蕾姆睡醒发现头上有根呆毛,这根呆毛在屏幕上的坐标到底是多少?
流程为:模型空间(
P
m
o
d
e
l
P_{model}
Pmodel)——>世界空间(
P
w
o
r
l
d
P_{world}
Pworld)——>观察空间(
P
v
i
e
w
P_{view}
Pview)——>裁剪空间(
P
c
l
i
p
P_{clip}
Pclip)——>屏幕空间
假设呆毛顶点的模型坐标为(0,2,4),扩展到齐次坐标系下为(0,2,4,1)
一、模型空间——>世界空间(模型变换)
计算其变换矩阵,注意顺序(缩放(zxy)、旋转、平移,从右向左)
M
m
o
d
e
l
=
[
1
0
0
t
x
0
1
0
t
y
0
0
1
t
z
0
0
0
1
]
[
c
o
s
(
θ
)
0
s
i
n
(
θ
)
0
0
1
0
0
−
s
i
n
(
θ
)
0
c
o
s
(
θ
)
0
0
0
1
]
[
k
x
0
0
0
0
k
y
0
0
0
0
k
z
0
0
0
0
1
]
M_{model}=\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&1 \end{bmatrix}\begin{bmatrix} k_{x}&0 &0 & 0\\ 0& k_{y} & 0 &0\\ 0& 0& k_{z}& 0\\ 0& 0& 0&1 \end{bmatrix}
Mmodel=⎣⎢⎢⎡100001000010txtytz1⎦⎥⎥⎤⎣⎢⎢⎡cos(θ)0−sin(θ)00100sin(θ)0cos(θ)0001⎦⎥⎥⎤⎣⎢⎢⎡kx0000ky0000kz00001⎦⎥⎥⎤
=
[
1
0
0
5
0
1
0
0
0
0
1
25
0
0
0
1
]
[
−
0.866
0
0.5
0
0
1
0
0
−
0.5
0
−
0.866
0
0
0
1
]
[
2
0
0
0
0
2
0
0
0
0
2
0
0
0
0
1
]
=\begin{bmatrix} 1&0 &0 & 5\\ 0& 1 & 0 &0 \\ 0& 0& 1& 25\\ 0& 0& 0&1 \end{bmatrix}\begin{bmatrix} -0.866&0 &0.5 & 0\\ 0& 1& 0 &0\\ -0.5& 0& -0.866\\ 0& 0& 0&1 \end{bmatrix}\begin{bmatrix} 2&0 &0 & 0\\ 0&2& 0 &0\\ 0& 0& 2& 0\\ 0& 0& 0&1 \end{bmatrix}
=⎣⎢⎢⎡10000100001050251⎦⎥⎥⎤⎣⎢⎢⎡−0.8660−0.5001000.50−0.8660001⎦⎥⎥⎤⎣⎢⎢⎡2000020000200001⎦⎥⎥⎤
=
[
−
1.732
0
1
5
0
2
0
0
−
1
0
−
1.732
25
0
0
0
1
]
=\begin{bmatrix} -1.732&0 &1 & 5\\ 0&2& 0 &0\\ -1& 0& -1.732& 25\\ 0& 0& 0&1 \end{bmatrix}
=⎣⎢⎢⎡−1.7320−10020010−1.732050251⎦⎥⎥⎤
计算其世界坐标
P
w
o
r
l
d
=
M
m
o
d
e
l
P
m
o
d
e
l
P_{world}=M_{model}P_{model}
Pworld=MmodelPmodel
=
[
−
1.732
0
1
5
0
2
0
0
−
1
0
−
1.732
25
0
0
0
1
]
[
0
2
4
1
]
=
[
9
4
18.072
1
]
=\begin{bmatrix} -1.732&0 &1 & 5\\ 0&2& 0 &0\\ -1& 0& -1.732& 25\\ 0& 0& 0&1 \end{bmatrix}\begin{bmatrix} 0\\ 2\\ 4\\ 1 \end{bmatrix}=\begin{bmatrix} 9\\ 4\\ 18.072\\ 1 \end{bmatrix}
=⎣⎢⎢⎡−1.7320−10020010−1.732050251⎦⎥⎥⎤⎣⎢⎢⎡0241⎦⎥⎥⎤=⎣⎢⎢⎡9418.0721⎦⎥⎥⎤
二、世界空间——>观察空间(观察变换)(右手坐标系)
这里变换矩阵两种求法,道理一样,搞不清的话直接按法一做,不影响。
法一:
M v i e w = M t r a n s l a t i o n M r o t a t i o n M s c a l e = [ 1 0 0 0 0 0.866 0.5 − 3.66 0 0.5 − 0.866 − 13.66 0 0 0 1 ] M_{view}=M_{translation}M_{rotation}M_{scale}=\begin{bmatrix} 1&0 &0 & 0\\ 0&0.866& 0.5&-3.66\\ 0& 0.5& -0.866& -13.66\\ 0& 0& 0&1 \end{bmatrix} Mview=MtranslationMrotationMscale=⎣⎢⎢⎡100000.8660.5000.5−0.86600−3.66−13.661⎦⎥⎥⎤
法二:
根据transform组件可以发现摄像机在世界空间中的变换经过了先旋转后平移(注意属性还是从下往上看,之后不再赘述),那么,要把摄像机变回初始状态就是先平移(0,-10,10)后旋转(-30,0,0),注意数值不是照抄。
M
v
i
e
w
=
M
r
o
t
a
t
i
o
n
M
t
r
a
n
s
l
a
t
i
o
n
M_{view}=M_{rotation}M_{translation}
Mview=MrotationMtranslation
两种方法结果一样,求观察坐标:
P
v
i
e
w
=
M
v
i
e
w
P
w
o
r
l
d
P_{view}=M_{view}P_{world}
Pview=MviewPworld
=
[
1
0
0
0
0
0.866
0.5
−
3.66
0
0.5
−
0.866
−
13.66
0
0
0
1
]
[
9
4
18.072
1
]
=
[
9
8.84
−
27.31
1
]
=\begin{bmatrix} 1&0 &0 & 0\\ 0&0.866& 0.5&-3.66\\ 0& 0.5& -0.866& -13.66\\ 0& 0& 0&1 \end{bmatrix}\begin{bmatrix} 9\\ 4\\ 18.072\\ 1 \end{bmatrix}=\begin{bmatrix} 9\\ 8.84\\ -27.31\\ 1 \end{bmatrix}
=⎣⎢⎢⎡100000.8660.5000.5−0.86600−3.66−13.661⎦⎥⎥⎤⎣⎢⎢⎡9418.0721⎦⎥⎥⎤=⎣⎢⎢⎡98.84−27.311⎦⎥⎥⎤
三、观察空间——>裁剪空间
3.1 透视投影
近、远裁剪平面高度:
n
e
a
r
C
l
i
p
P
l
a
n
e
H
e
i
g
h
t
=
2
⋅
N
e
a
r
⋅
tan
F
O
V
2
nearClipPlaneHeight=2\cdot Near\cdot \tan \frac{FOV}{2}
nearClipPlaneHeight=2⋅Near⋅tan2FOV
f
a
r
C
l
i
p
P
l
a
n
e
H
e
i
g
h
t
=
2
⋅
F
a
r
⋅
tan
F
O
V
2
farClipPlaneHeight=2\cdot Far\cdot \tan \frac{FOV}{2}
farClipPlaneHeight=2⋅Far⋅tan2FOV
摄像机横纵比:
A s p e c t = n e a r C l i p P l a n e W i d t h n e a r P l a n e H e i g h t Aspect=\frac{nearClipPlaneWidth}{nearPlaneHeight} Aspect=nearPlaneHeightnearClipPlaneWidth
A s p e c t = f a r C l i p P l a n e W i d t h f a r P l a n e H e i g h t Aspect=\frac{farClipPlaneWidth}{farPlaneHeight} Aspect=farPlaneHeightfarClipPlaneWidth
裁剪矩阵(也叫投影矩阵):
M
f
r
u
s
t
u
m
=
[
cot
F
O
V
2
A
s
p
e
c
t
0
0
0
0
cot
F
O
V
2
0
0
0
0
−
F
a
r
+
N
e
a
r
F
a
a
r
−
N
e
a
r
−
2
⋅
N
e
a
r
⋅
F
a
r
F
a
r
−
N
e
a
r
0
0
−
1
0
]
M_{frustum}=\begin{bmatrix} \frac{\cot \frac{FOV}{2}}{Aspect} & 0& 0 & 0\\ 0& \cot \frac{FOV}{2}& 0& 0\\ 0 & 0 & -\frac{Far+Near}{Faar-Near} &-\frac{2\cdot Near\cdot Far}{Far-Near} \\ 0 & 0 & -1 &0 \end{bmatrix}
Mfrustum=⎣⎢⎢⎢⎡Aspectcot2FOV0000cot2FOV0000−Faar−NearFar+Near−100−Far−Near2⋅Near⋅Far0⎦⎥⎥⎥⎤
裁剪坐标(本质上就是对x,y,z缩放,z还多了个平移):
P
c
l
i
p
=
M
f
r
u
s
t
u
m
P
v
i
e
w
P_{clip}=M_{frustum}P_{view}
Pclip=MfrustumPview
= [ cot F O V 2 A s p e c t 0 0 0 0 cot F O V 2 0 0 0 0 − F a r + N e a r F a a r − N e a r − 2 ⋅ N e a r ⋅ F a r F a r − N e a r 0 0 − 1 0 ] [ x y z 1 ] =\begin{bmatrix} \frac{\cot \frac{FOV}{2}}{Aspect} & 0& 0 & 0\\ 0& \cot \frac{FOV}{2}& 0& 0\\ 0 & 0 & -\frac{Far+Near}{Faar-Near} &-\frac{2\cdot Near\cdot Far}{Far-Near} \\ 0 & 0 & -1 &0 \end{bmatrix}\begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} =⎣⎢⎢⎢⎡Aspectcot2FOV0000cot2FOV0000−Faar−NearFar+Near−100−Far−Near2⋅Near⋅Far0⎦⎥⎥⎥⎤⎣⎢⎢⎡xyz1⎦⎥⎥⎤
= [ x cot F O V 2 A s p e c t y cot F O V 2 − z F a r + N e a r F a a r − N e a r − 2 ⋅ N e a r ⋅ F a r F a r − N e a r − z ] =\begin{bmatrix} x\frac{\cot \frac{FOV}{2}}{Aspect}\\ y \cot \frac{FOV}{2}\\ -z\frac{Far+Near}{Faar-Near} -\frac{2\cdot Near\cdot Far}{Far-Near}\\ -z \end{bmatrix} =⎣⎢⎢⎢⎡xAspectcot2FOVycot2FOV−zFaar−NearFar+Near−Far−Near2⋅Near⋅Far−z⎦⎥⎥⎥⎤
变换后的坐标必须满足 x , y , z ϵ [ − ω , ω ] x,y,z\epsilon [-\omega ,\omega ] x,y,zϵ[−ω,ω],其中 ω \omega ω的值为原先的 − z -z −z(就是结果中前三个数在第四个数的正负范围内),不满足这个条件的图元那就舍弃或裁剪。
带入数值:
P
c
l
i
p
=
M
f
r
u
s
t
u
m
P
v
i
e
w
=
[
1.299
0
0
0
0
1.732
0
0
0
0
−
1.286
−
11.429
0
0
−
1
0
]
[
9
8.84
−
27.31
1
]
P_{clip}=M_{frustum}P_{view}=\begin{bmatrix} 1.299&0 &0 & 0\\ 0&1.732& 0&0\\ 0& 0& -1.286& -11.429\\ 0& 0& -1&0 \end{bmatrix}\begin{bmatrix} 9\\ 8.84\\ -27.31\\ 1 \end{bmatrix}
Pclip=MfrustumPview=⎣⎢⎢⎡1.29900001.7320000−1.286−100−11.4290⎦⎥⎥⎤⎣⎢⎢⎡98.84−27.311⎦⎥⎥⎤
=
[
11.691
15.311
23.693
27.31
]
=\begin{bmatrix} 11.691\\ 15.311\\ 23.693\\ 27.31 \end{bmatrix}
=⎣⎢⎢⎡11.69115.31123.69327.31⎦⎥⎥⎤
x
,
y
,
z
x,y,z
x,y,z都在-27.31~27.31的范围内,不用裁剪或舍弃
3.2 正交投影
n
e
a
r
C
l
i
p
P
l
a
n
e
H
e
i
g
h
t
=
f
a
r
C
l
i
p
P
l
a
n
e
H
e
i
g
h
t
=
2
⋅
S
i
z
e
nearClipPlaneHeight=farClipPlaneHeight=2\cdot Size
nearClipPlaneHeight=farClipPlaneHeight=2⋅Size
n
e
a
r
C
l
i
p
P
l
a
n
e
W
i
d
t
h
=
f
a
r
C
l
i
p
P
l
a
n
e
W
i
d
t
h
nearClipPlaneWidth=farClipPlaneWidth
nearClipPlaneWidth=farClipPlaneWidth
=
A
s
p
e
c
t
⋅
n
e
a
r
C
l
i
p
P
l
a
n
e
H
e
i
g
h
t
=Aspect\cdot nearClipPlaneHeight
=Aspect⋅nearClipPlaneHeight
裁剪矩阵:
M o r t h o = [ 1 A s p e c t ⋅ S i z e 0 0 0 0 1 S i z e 0 0 0 0 − 2 F a a r − N e a r − F a r + N e a r F a a r − N e a r 0 0 0 1 ] M_{ortho}=\begin{bmatrix} \frac{1}{Aspect\cdot Size}& 0 & 0 & 0\\ 0& \frac{1}{Size}& 0 & 0\\ 0 & 0 &-\frac{2}{Faar-Near} &-\frac{Far+Near}{Faar-Near} \\ 0& 0 &0 &1 \end{bmatrix} Mortho=⎣⎢⎢⎡Aspect⋅Size10000Size10000−Faar−Near2000−Faar−NearFar+Near1⎦⎥⎥⎤
裁剪坐标:
P
c
l
i
p
=
M
o
r
t
h
o
P
v
i
e
w
P_{clip}=M_{ortho}P_{view}
Pclip=MorthoPview
= [ x A s p e c t ⋅ S i z e y S i z e − 2 z F a a r − N e a r − F a r + N e a r F a r − N e a r 1 ] =\begin{bmatrix} \frac{x}{Aspect\cdot Size}\\ \frac{y}{Size}\\ -\frac{2z}{Faar-Near} -\frac{Far+Near}{Far-Near}\\ 1 \end{bmatrix} =⎣⎢⎢⎡Aspect⋅SizexSizey−Faar−Near2z−Far−NearFar+Near1⎦⎥⎥⎤
四、裁剪空间——>屏幕空间
在这一步中有两个步骤:1.通过齐次除法得NDC坐标; 2.屏幕映射(就是一个缩放过程)
合在一起的公式:
s
c
r
e
e
n
x
=
c
l
i
p
x
⋅
p
i
x
e
l
W
i
d
t
h
2
⋅
c
l
i
p
ω
+
p
i
x
e
l
W
i
d
t
h
2
screen_{x}=\frac{clip_{x}\cdot pixelWidth}{2\cdot clip_{\omega }}+\frac{pixelWidth}{2}
screenx=2⋅clipωclipx⋅pixelWidth+2pixelWidth
s c r e e n y = c l i p y ⋅ p i x e l H e i g h t 2 ⋅ c l i p ω + p i x e l H e i g h t 2 screen_{y}=\frac{clip_{y}\cdot pixelHeight}{2\cdot clip_{\omega }}+\frac{pixelHeight}{2} screeny=2⋅clipωclipy⋅pixelHeight+2pixelHeight
上一步中通过透视法求出的裁剪坐标为(11.691,15.311,23.692,27.31)
假设像素宽度为400,高度为300,那么,把它投影到NDC再映射到屏幕空间中的过程为:
s
c
r
e
e
n
x
=
11.691
⋅
400
2
⋅
27.31
+
400
2
=
285.617
screen_{x}=\frac{11.691\cdot 400}{2\cdot 27.31}+\frac{400}{2}=285.617
screenx=2⋅27.3111.691⋅400+2400=285.617
s c r e e n y = 15.311 ⋅ 300 2 ⋅ 27.31 + 300 2 = 234.096 screen_{y}=\frac{15.311\cdot 300}{2\cdot 27.31}+\frac{300}{2}=234.096 screeny=2⋅27.3115.311⋅300+2300=234.096
得出,呆毛在屏幕上的像素位置为(285.617,234.096)。
五、总结
蕾姆不会长呆毛。