透视投影矩阵的推导

空间变换
上图是3D渲染过程中的空间变换过程,这里主要讨论观察空间到裁剪空间的转换。

由上图可知,经过观察变换后,空间变换为观察空间,也就是以摄像机坐标为原点的空间,这是接下来推导的前提。

下图是一个视锥体,在视锥体范围内的物体为可视的,不在视锥体内的为不可视。
视锥体
我们有两个任务:
1、判断一个点是否在视锥体内(用于裁剪超出屏幕的点)。
2、计算顶点在裁剪空间上的坐标。
我们先忘掉矩阵的概念,只用基本的三维几何知识完成第一点。

先假定一个场景如下图:image.png
已知以下参数:
fov:视锥体上下两个截面的夹角,此参数由设定摄像机参数时给定了
n:近截面z轴坐标,此参数由设定摄像机参数时给定了
f:远截面z轴坐标,此参数由设定摄像机参数时给定了
aspect:屏幕宽高比,此参数由设定摄像机参数时给定了
H:平行于远截面,并且经过P点的平面的高的一半,可通过计算得出

由此,我们只需要判断P点的y轴坐标除以H是否大于1(当y为负时是否小于-1),即可知道P点是否在y轴方向上超出了视椎体。同理可求出x轴。

下面先求y方向。
H = z ∗ t a n ( f o v / 2 ) H=z*tan(fov/2) H=ztan(fov/2)
y / H = y / z ∗ t a n ( f o v / 2 ) y/H=y/z*tan(fov/2) y/H=y/ztan(fov/2)

接下来求x方向,假设经过此P点截面的宽度为W
W = a s p e c t ∗ H W=aspect*H W=aspectH
W = a s p e c t ∗ z ∗ t a n ( f o v / 2 ) W=aspect*z*tan(fov/2) W=aspectztan(fov/2)
x / W = x / ( a s p e c t ∗ z ∗ t a n ( f o v / 2 ) ) x/W=x/(aspect*z*tan(fov/2)) x/W=x/(aspectztan(fov/2))

最后求z方向
( z − n ) / ( f − n ) (z-n)/(f-n) (zn)/(fn)

我们已经获得计算点是否在视锥体内的计算方式,现在我们把它转换为矩阵的形式,设M为我们要求的转换矩阵,可得:
M ⋅ [ x y z 1 ] = [ x a s p e c t ∗ z ∗ t a n ( f o v / 2 ) y z ∗ t a n ( f o v / 2 ) ( z − n ) / ( f − n ) 1 ] M \cdot \left[\begin{matrix} x \\ y \\ z \\ 1 \end{matrix}\right] = \left[\begin{matrix} \frac{x}{aspect*z*tan(fov/2)} \\ \frac{y}{z*tan(fov/2)} \\ (z-n)/(f-n) \\ 1 \end{matrix} \right] Mxyz1=aspectztan(fov/2)xztan(fov/2)y(zn)/(fn)1
[ m 00 m 01 m 02 m 03 m 10 m 11 m 12 m 13 m 20 m 21 m 22 m 23 m 30 m 31 m 32 m 33 ] ⋅ [ x y z 1 ] = [ x a s p e c t ∗ z ∗ t a n ( f o v / 2 ) y z ∗ t a n ( f o v / 2 ) ( z − n ) / ( f − n ) 1 ] \left[ \begin{matrix} m_{00} & m_{01} & m_{02} & m_{03}\\ m_{10} & m_{11} & m_{12} & m_{13} \\ m_{20} & m_{21} & m_{22} & m_{23} \\ m_{30} & m_{31} & m_{32} & m_{33} \end{matrix} \right] \cdot \left[\begin{matrix} x \\ y \\ z \\ 1 \end{matrix}\right] = \left[\begin{matrix} \frac{x}{aspect*z*tan(fov/2)} \\ \frac{y}{z*tan(fov/2)} \\ (z-n)/(f-n) \\ 1 \end{matrix} \right] m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33xyz1=aspectztan(fov/2)xztan(fov/2)y(zn)/(fn)1

我们发现求解 m 00 ∗ x + m 01 ∗ y + m 02 ∗ z + m 03 = x z ∗ a s p e c t ∗ t a n ( f o v / 2 ) m_{00}*x + m_{01}*y + m_{02}*z + m_{03} = \frac{x}{z*aspect*tan(fov/2)} m00x+m01y+m02z+m03=zaspecttan(fov/2)x很难找出合适的 m 00 m_{00} m00 m 02 m_{02} m02,因为左边x和z是以加法的形式相邻,右边z确成为了x的分母。

解决方法:将右边的齐次坐标每一项乘以z,所以有:
[ m 00 m 01 m 02 m 03 m 10 m 11 m 12 m 13 m 20 m 21 m 22 m 23 m 30 m 31 m 32 m 33 ] ⋅ [ x y z 1 ] = [ x a s p e c t ∗ t a n ( f o v / 2 ) y t a n ( f o v / 2 ) z ∗ ( z − n ) / ( f − n ) z ] \left[ \begin{matrix} m_{00} & m_{01} & m_{02} & m_{03}\\ m_{10} & m_{11} & m_{12} & m_{13} \\ m_{20} & m_{21} & m_{22} & m_{23} \\ m_{30} & m_{31} & m_{32} & m_{33} \end{matrix} \right] \cdot \left[\begin{matrix} x \\ y \\ z \\ 1 \end{matrix}\right] = \left[\begin{matrix} \frac{x}{aspect*tan(fov/2)} \\ \frac{y}{tan(fov/2)} \\ z*(z-n)/(f-n) \\ z \end{matrix} \right] m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33xyz1=aspecttan(fov/2)xtan(fov/2)yz(zn)/(fn)z

所以可以求得矩阵为:
[ 1 a s p e c t ∗ t a n ( f o v / 2 ) 0 0 0 0 1 t a n ( f o v / 2 ) 0 0 0 0 m 22 m 23 0 0 1 0 ] \left[ \begin{matrix} \frac{1}{aspect*tan(fov/2)} & 0 & 0 & 0\\ 0 & \frac{1}{tan(fov/2)} & 0 & 0 \\ 0 & 0 & m_{22} & m_{23} \\ 0 & 0 & 1 & 0 \end{matrix} \right] aspecttan(fov/2)10000tan(fov/2)10000m22100m230

m 22 ∗ z + m 23 = z ∗ ( z − n ) / ( f − n ) m_{22}*z + m_{23} = z*(z-n)/(f-n) m22z+m23=z(zn)/(fn)

我们知道,当 z = n z=n z=n时, ( z − n ) / ( f − n ) = − 1 (z-n)/(f-n)=-1 (zn)/(fn)=1 所以 m 22 ∗ n + m 23 = − n m_{22}*n + m_{23} = -n m22n+m23=n

z = f z=f z=f时, ( z − n ) / ( f − n ) = 1 (z-n)/(f-n)=1 (zn)/(fn)=1 所以 m 22 ∗ f + m 23 = f m_{22}*f + m_{23} = f m22f+m23=f

联 立 { m 22 ∗ n + m 23 = − n m 22 ∗ f + m 23 = f 联立 \begin{cases} m_{22}*n + m_{23} = -n \\ m_{22}*f + m_{23} = f \end{cases} {m22n+m23=nm22f+m23=f

求 得 { m 22 = − f − n n − f m 23 = 2 ∗ f ∗ n n − f 求得 \begin{cases} m_{22} = \frac{-f-n}{n-f} \\ m_{23} = \frac{2*f*n}{n-f} \end{cases} {m22=nffnm23=nf2fn

最后求得投影矩阵为:
[ 1 a s p e c t ∗ t a n ( f o v / 2 ) 0 0 0 0 1 t a n ( f o v / 2 ) 0 0 0 0 − f − n n − f 2 ∗ f ∗ n n − f 0 0 1 0 ] \left[ \begin{matrix} \frac{1}{aspect*tan(fov/2)} & 0 & 0 & 0\\ 0 & \frac{1}{tan(fov/2)} & 0 & 0 \\ 0 & 0 & \frac{-f-n}{n-f} & \frac{2*f*n}{n-f} \\ 0 & 0 & 1 & 0 \end{matrix} \right] aspecttan(fov/2)10000tan(fov/2)10000nffn100nf2fn0

注意,通过此矩阵转换后的坐标是齐次坐标,只要除以w分量,根据结果就可以判断是否在[-1,1]范围内,也就是该点是否在视椎体内。

透视投影矩阵只是为了获得一个齐次坐标,为投影做准备,实际不进行真正的投影,真正的屏幕投影是在下一个阶段执行的。

相较于https://www.cnblogs.com/bluebean/p/5276111.html,本文是用另外一种几何思路推导透视投影矩阵,可以互相参考。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值