1、透视矩阵
推导过程
其中
z
在光栅化过程中不按线性插值,而是按
1/z
做线性插值,证明如下:
如图为
x−z
平面上一条与三角形的某一扫描线对应的线段,设直线方程为
ax+bz=c
且
c≠0
直线上的坐标为
<x,z>
的点在相机近平面的投影为
<p,−e>
通过三角形相似可得:
p/x=−e/z
将其带入直线方程可得:
(−ap/e+b)z=c
整理可得:
1/z=−ap/ec+b/c
(1)
x1,z1,x2,z2
为直线上的点,在相机近平面上的投影为
p1,p2
,现设一点
<x3,z3>
在近平面的投影为
p3
, 因为近平面上的
x
坐标满足线性插值,可得:
p3=(1−t)p1+tp2,∀t∈[0,1]
带入
(1)
可得
1z3=(−ap1/ce+b/c)(1−t)+(−ap2/ce+b/c)t=1z1(1−t)+1z3t
2、Viewport Transform
Viewport Transform在OpenGL管线中的位置如图,其过程如下:
3、DepthBuffer
顶点的
z
值在进行透视变换后为
zclip=−zviewf+nf−n−2nff−n
经过齐次除法后NDC空间的
zndc=zclipwclip=f+nf−n+2nf(f−n)zview
由Viewport Transform可知DepthBuffer中的
zdepth=1/2⋅zndc+1/2
代入
zndc
可得:
zview=1f−nfnd−1n
取反后除以
f
即可映射到
[0,1]
中。
4、Unity的内置数学函数
该函数将depth buffer中的深度映射到
[n,f]
中
其中
注释中的链接作者表示,他也不确定,反正能用 - -!,下面的推导有时间再去试试看。
其中LinearEyeDepth函数就是实现了
zview=1f−nfnd−1n
然后取反的操作
Linear01Depth函数则是多除了一个
f
将其映射到
[0,1]
5、留着以后慢慢记录