推导投影矩阵


同步自:https://dingyujie-23.gitee.io/2023/10/22/投影变换与矩阵推导/

前言

本文主要目的是推导投影矩阵。曾经刚了解投影矩阵的时候,面对网上搜到的各种各样的推导非常头疼,因为他们推导前提条件和结果都不一样。本文会在非常明确的前提下推导出投影矩阵,并简略说明Games 101《Unity Shader入门精要》中的投影矩阵的不同之处。

首先明确一点,推导投影矩阵时假设的前提条件不一样时(比如:视锥体位置、左手系或右手系、摄像机看向z轴正方向还是负方向、已知的参数等),推导出的结果会有所不同,。本文的推导过程假设使用右手系,摄像机看向z轴负方向已知的参数和视锥体位置另有说明

正交投影

首先假设视锥体近平面位于z = 0处,则视锥体远平面位于z = n-f处(z < 0),则

z ∈ [ n − f , 0 ] z\in[n - f,0] z[nf,0]

假设近平面的中心位于坐标原点,设视锥体中x和y的取值范围如下:

x ∈ [ − r , r ] , r > 0 x\in[-r, r],r > 0 x[r,r],r>0
y ∈ [ − t , t ] , t > 0 y\in[-t, t],t > 0 y[t,t],t>0

在视锥体内有一点 P ( x p , y p , z p ) P(x_p, y_p, z_p) P(xp,yp,zp)位于视锥体内,如下图所示。

在这里插入图片描述

我们的目标是将视锥体内任意一点 P P P的坐标变换至 x , y , z ∈ [ − 1 , 1 ] x,y,z\in[-1 ,1] x,y,z[1,1],变换后的示意图如下:

在这里插入图片描述

为了达到这个目的,我们需要将点P的 x , y , z x, y, z x,y,z坐标分别进行缩放:

x p ′ = 1 r x p x_p' = \frac{1}{r}x_p xp=r1xp
y p ′ = 1 t y p y_p' = \frac{1}{t}y_p yp=t1yp
z p ′ = 2 n − f x p − 1 z_p' = \frac{2}{n - f}x_p - 1 zp=nf2xp1

则对应的矩阵为:

[ 1 r 0 0 0 0 1 t 0 0 0 0 2 n − f − 1 0 0 0 1 ] \begin{bmatrix} \frac{1}{r} & 0 & 0 & 0 \\\\ 0 & \frac{1}{t} & 0 & 0 \\\\ 0 & 0 & \frac{2}{n - f} & -1 \\\\ 0 & 0 & 0 & 1 \end{bmatrix} r10000t10000nf200011

在Unity中,我们一般使用另外的参数来描述正交相机,即: t = s i z e t = size t=size a s p e c t = r / t aspect = r / t aspect=r/t,则 r = t ⋅ a s p e c t r = t \cdot aspect r=taspect,于是投影矩阵可以表示为:

[ 1 a s p e c t ⋅ t 0 0 0 0 1 s i z e 0 0 0 0 2 n − f − 1 0 0 0 1 ] 正交投影矩阵一 \begin{bmatrix} \frac{1}{aspect\cdot t} & 0 & 0 & 0 \\\\ 0 & \frac{1}{size} & 0 & 0 \\\\ 0 & 0 & \frac{2}{n - f} & -1 \\\\ 0 & 0 & 0 & 1 \end{bmatrix} \tag*{正交投影矩阵一} aspectt10000size10000nf200011正交投影矩阵一

注意,这个正交投影矩阵与Games 101《Unity Shader入门精要》中的正交投影矩阵都不相同。

与本节的假设相比,《Unity Shader入门精要》第81页中的正交投影矩阵假设原始视锥体的近平面并没有位于 z = 0 z=0 z=0处,而是位于 z = − n z=-n z=n处,即对于原始视锥体中的任意一点, z ∈ [ − f , − n ] z\in[-f, -n] z[f,n],其正交投影矩阵如下:

[ 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 n − f n + f n − f 0 0 0 1 ] 正交投影矩阵二 \begin{bmatrix} \frac{1}{aspect\cdot size} & 0 & 0 & 0 \\\\ 0 & \frac{1}{size} & 0 & 0 \\\\ 0 & 0 & \frac{2}{n - f} & \frac{n + f}{n - f} \\\\ 0 & 0 & 0 & 1 \end{bmatrix} \tag*{正交投影矩阵二} aspectsize10000size10000nf2000nfn+f1正交投影矩阵二

与本节的假设相比,Games 101中的投影矩阵的推导,假设视锥体位于任何位置(但视锥体始终与坐标轴平行),具体推导可以见:GAMES101-现代计算机图形学入门-闫令琪

透视投影

对于透视投影,其视锥体为一个平截头体(frustum),我们先考虑将其"压缩",即保持近平面不变,将其"压缩"为一个立方体,然后利用透视投影的方法得到结果。

假设平截头体所在四棱锥的顶尖位于坐标原点,朝向z轴负方向,并且关于x轴和y轴对称,有一点 P ( x p , y p , z p ) P(x_p, y_p, z_p) P(xp,yp,zp)位于视锥体内,如下图所示:

在这里插入图片描述

首先考虑点 P P P的坐标 x p x_p xp,我们从下往上去看(或者从上往下看,一样的),如下图所示:

在这里插入图片描述

则可以很容易的由相似三角形得到变换后的坐标

x p ′ = n − z p x p x_p' = \frac{n}{-z_p}x_p xp=zpnxp

同理可得(懒得画图了):

y p ′ = n − z p y p y_p' = \frac{n}{-z_p}y_p yp=zpnyp

我们暂时先不处理 z p ′ z_p' zp。由于式子中含有 − z p -z_p zp,无法直接写在矩阵当中,所以接下来需要经过一些特别的处理。我们知道,对于齐次坐标:

[ x p y p z p 1 ] 和 [ n x p n y p n z p n ] \begin{bmatrix} x_p\\\\ y_p \\\\ z_p \\\\ 1 \end{bmatrix} 和 \begin{bmatrix} nx_p\\\\ ny_p \\\\ nz_p \\\\ n \end{bmatrix} xpypzp1nxpnypnzpn

这两个齐次坐标表示三维空间中的同一个点。如果我们某一次计算的结果是后一种,则"隐含了"接下来要除以n的操作。因此我们得到如下矩阵:

[ n 0 0 0 0 n 0 0 ? ? ? ? 0 0 − 1 0 ] \begin{bmatrix} n & 0 & 0 & 0 \\\\ 0 & n & 0 & 0 \\\\ ? & ? & ? & ? \\\\ 0 & 0 & -1 & 0 \end{bmatrix} n0?00n?000?100?0* [ x p y p z p 1 ] \begin{bmatrix} x_p\\\\ y_p \\\\ z_p \\\\ 1 \end{bmatrix} xpypzp1 = [ n x p n y p ? − z p ] \begin{bmatrix} nx_p\\\\ ny_p \\\\ ? \\\\ -z_p \end{bmatrix} nxpnyp?zp

这个矩阵已经可以完美描述 x p x_p xp x p x_p xp的变换了,对于 z p z_p zp,我们无法简单的找到公式,但是我们发现对于近平面和远平面内的点,变换后的 z p ′ = z p z_p' = z_p zp=zp,而位于视锥体内部的点则不一定。并且 z p ′ z_p' zp x p x_p xp y p y_p yp无关,于是我们可以根据近平面和远平面上的点列出式子。

对于近平面,其 z p = − n z_p = -n zp=n

[ n 0 0 0 0 n 0 0 0 0 A B 0 0 − 1 0 ] \begin{bmatrix} n & 0 & 0 & 0 \\\\ 0 & n & 0 & 0 \\\\ 0 & 0 & A & B \\\\ 0 & 0 & -1 & 0 \end{bmatrix} n0000n0000A100B0 * [ x p y p − n 1 ] \begin{bmatrix} x_p\\\\ y_p \\\\ -n \\\\ 1 \end{bmatrix} xpypn1 = [ n x p n y p − n 2 n ] \begin{bmatrix} nx_p\\\\ ny_p \\\\ -n^2 \\\\ n \end{bmatrix} nxpnypn2n ,即: [ 0 , 0 , A , B ] [0, 0, A, B] [0,0,A,B] * [ x p y p − n 1 ] \begin{bmatrix} x_p\\\\ y_p \\\\ -n \\\\ 1 \end{bmatrix} xpypn1 = − n 2 -n^2 n2

对于远平面,其 z p = − f z_p = -f zp=f

[ n 0 0 0 0 n 0 0 0 0 A B 0 0 − 1 0 ] \begin{bmatrix} n & 0 & 0 & 0 \\\\ 0 & n & 0 & 0 \\\\ 0 & 0 & A & B \\\\ 0 & 0 & -1 & 0 \end{bmatrix} n0000n0000A100B0 * [ x p y p − f 1 ] \begin{bmatrix} x_p\\\\ y_p \\\\ -f \\\\ 1 \end{bmatrix} xpypf1 = [ n x p n y p − f 2 f ] \begin{bmatrix} nx_p\\\\ ny_p \\\\ -f^2 \\\\ f \end{bmatrix} nxpnypf2f ,即: [ 0 , 0 , A , B ] [0, 0, A, B] [0,0,A,B] * [ x p y p − f 1 ] \begin{bmatrix} x_p\\\\ y_p \\\\ -f \\\\ 1 \end{bmatrix} xpypf1 = − f 2 -f^2 f2

解这个方程组即可得到:

A = n + f A=n+f A=n+f

B = n f B=nf B=nf

B B B的值与Games 101中推导出的值 ( B = − n f ) (B=-nf) B=nf不同(大概是因为他们假设 z ∈ [ n , f ] z\in[n, f] z[n,f],与我们的假设不同)。

于是可得矩阵

[ n 0 0 0 0 n 0 0 0 0 n + f n f 0 0 − 1 0 ] 透视投影矩阵一 \begin{bmatrix} n & 0 & 0 & 0 \\\\ 0 & n & 0 & 0 \\\\ 0 & 0 & n+f & nf \\\\ 0 & 0 & -1 & 0 \end{bmatrix} \tag*{透视投影矩阵一} n0000n0000n+f100nf0透视投影矩阵一

经过透视投影矩阵一投影后,原视锥体由平截头体变为一个立方体,坐标取值范围为 x ∈ [ − r , r ] x\in[-r, r] x[r,r] y ∈ [ − t , t ] y\in[-t, t] y[t,t] z ∈ [ − f , − n ] z\in[-f, -n] z[f,n],再次对其应用正交投影矩阵二:

[ 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 n − f n + f n − f 0 0 0 1 ] \begin{bmatrix} \frac{1}{aspect\cdot size} & 0 & 0 & 0 \\\\ 0 & \frac{1}{size} & 0 & 0 \\\\ 0 & 0 & \frac{2}{n - f} & \frac{n + f}{n - f} \\\\ 0 & 0 & 0 & 1 \end{bmatrix} aspectsize10000size10000nf2000nfn+f1 * [ n 0 0 0 0 n 0 0 0 0 n + f n f 0 0 − 1 0 ] \begin{bmatrix} n & 0 & 0 & 0 \\\\ 0 & n & 0 & 0 \\\\ 0 & 0 & n+f & nf \\\\ 0 & 0 & -1 & 0 \end{bmatrix} n0000n0000n+f100nf0 =
[ n a s p e c t ⋅ s i z e 0 0 0 0 n s i z e 0 0 0 0 n + f n − f 2 n f n − f 0 0 − 1 0 ] 透视投影矩阵二 \begin{bmatrix} \frac{n}{aspect\cdot size} & 0 & 0 & 0 \\\\ 0 & \frac{n}{size} & 0 & 0 \\\\ 0 & 0 & \frac{n+f}{n - f} & \frac{2nf}{n-f} \\\\ 0 & 0 & -1 & 0 \end{bmatrix} \tag*{透视投影矩阵二} aspectsizen0000sizen0000nfn+f100nf2nf0透视投影矩阵二

接下来是换参数的问题。在Unity中,透视相机由 a s p e c t aspect aspect f o v fov fov n e a r ( n ) near(n) near(n) f a r ( f ) far(f) far(f)定义

cot ⁡ f o v 2 = n s i z e \cot\frac{fov}{2} = \frac{n}{size} cot2fov=sizen

所以最终的透视投影矩阵可以写为

[ cot ⁡ f o v 2 a s p e c t 0 0 0 0 cot ⁡ f o v 2 0 0 0 0 n + f n − f 2 n f n − f 0 0 − 1 0 ] 透视投影矩阵三 \begin{bmatrix} \frac{\cot\frac{fov}{2}}{aspect} & 0 & 0 & 0 \\\\ 0 & \cot\frac{fov}{2} & 0 & 0 \\\\ 0 & 0 & \frac{n+f}{n - f} & \frac{2nf}{n-f} \\\\ 0 & 0 & -1 & 0 \end{bmatrix} \tag*{透视投影矩阵三} aspectcot2fov0000cot2fov0000nfn+f100nf2nf0透视投影矩阵三

透视投影矩阵三《Unity Shader入门精要》第79页的矩阵相同。

对本文有任何疑问,欢迎指出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
透视投影变换矩阵推导过程如下: 假设有一个三维点 $(X,Y,Z)$,它在相机坐标系中的坐标为 $(X_c,Y_c,Z_c)$。相机坐标系的原点为相机位置,$Z_c$ 轴指向相机朝向的反方向,$X_c$ 和 $Y_c$ 轴分别与相机的右方向和下方向对齐。 为了把相机坐标系中的点映射到图像平面上,我们需要进行透视投影变换。首先,我们将相机坐标系中的点转换为齐次坐标 $(X_c,Y_c,Z_c,1)$。然后,我们将它乘以一个投影矩阵 $P$,得到一个新的齐次坐标 $(u,v,w,1)$: $$ \begin{bmatrix} u \\ v \\ w \\ 1 \\ \end{bmatrix} = P \cdot \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ 1 \\ \end{bmatrix} $$ 其中,$u$ 和 $v$ 分别表示图像平面上的坐标,$w$ 用来进行透视除法,保证 $u$ 和 $v$ 的值在图像平面上。 投影矩阵 $P$ 可以分解为相机内参矩阵 $K$ 和相机外参矩阵 $[R|t]$ 的乘积: $$ P = K [R|t] $$ 其中,$K$ 是一个 $3 \times 3$ 的矩阵,包含了相机的内部参数,如焦距、主点等。$[R|t]$ 是一个 $3 \times 4$ 的矩阵,包含了相机的外部参数,如相机的旋转和平移。 为了推导 $P$ 的具体形式,我们可以先考虑一个简单的情况:相机坐标系的原点与图像平面重合,且相机的朝向与图像平面平行。这种情况下,投影矩阵可以表示为: $$ P = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} $$ 其中,$f$ 是焦距,表示相机到图像平面的距离。 当相机坐标系的原点和图像平面不重合时,我们可以使用相机外参矩阵 $[R|t]$ 来把相机坐标系的原点变换到图像平面上。具体来说,我们可以将相机坐标系的原点变换为 $(X_c',Y_c',Z_c')$,其中 $(X_c',Y_c',0)$ 是图像平面上的点。这个变换可以表示为: $$ \begin{bmatrix} X_c' \\ Y_c' \\ Z_c' \\ 1 \\ \end{bmatrix} = [R|t] \cdot \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \\ \end{bmatrix} $$ 然后,我们可以把 $(X,Y,Z)$ 变换为 $(X',Y',Z')$,其中 $(X',Y')$ 是图像平面上的坐标。这个变换可以表示为: $$ \begin{bmatrix} X' \\ Y' \\ Z' \\ 1 \\ \end{bmatrix} = [R|t] \cdot \begin{bmatrix} X \\ Y \\ Z \\ 1 \\ \end{bmatrix} $$ 最后,我们可以将 $(X',Y',Z')$ 投影到图像平面上,得到一个新的齐次坐标 $(u,v,w,1)$。这个投影可以表示为: $$ \begin{bmatrix} u \\ v \\ w \\ 1 \\ \end{bmatrix} = K \cdot \begin{bmatrix} X'/Z' \\ Y'/Z' \\ 1 \\ \end{bmatrix} $$ 将以上三个变换组合起来,我们可以得到透视投影变换矩阵的形式: $$ P = K [R|t] = \begin{bmatrix} f_x & 0 & c_x & 0 \\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \\ \end{bmatrix} $$ 其中,$f_x$ 和 $f_y$ 是 $K$ 矩阵的对角线元素,分别表示 $x$ 和 $y$ 方向上的焦距;$c_x$ 和 $c_y$ 是 $K$ 矩阵的中心点,表示图像平面上的主点;$r_{ij}$ 和 $t_i$ 是 $[R|t]$ 矩阵的元素,表示相机的旋转和平移。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值