回顾Games101图形学(一)几何变换中一些公式的推导

回顾Games101 chapter 1 - 6

前言

本文只写回顾后重新加深认识的知识

透视除法的意义

经过MVP矩阵之后,将模型空间下某点的坐标,转换成了裁剪空间下的坐标,此时因为裁剪空间的范围是 x ∈ [ − W / 2 , W / 2 ] x∈[-W/2,W/2] x[W/2W/2] y ∈ [ − H / 2 , H / 2 ] y∈[-H/2,H/2] y[H/2H/2],所以经过以下两个变换,其中除以pz就是透视除法
一:
− 1 ≤ 2 ⋅ ( p x p z ⋅ n e a r ) w ≤ 1 − 1 ≤ 2 ⋅ ( p y p z ⋅ n e a r ) h ≤ 1 -1≤2·\frac{\left( \frac{p_x}{p_z}·near \right)}{w}≤1 \\ -1≤2·\frac{\left( \frac{p_y}{p_z}·near \right)}{h}≤1 12w(pzpxnear)112h(pzpynear)1
二:
[ x y z w ] [ 1 0 0 0 0 1 0 0 0 0 1 0 Δ x Δ y Δ z 1 ] = [ x + Δ x ∗ w y + Δ y ∗ w z + Δ z ∗ w w ] \left[ \begin{matrix} x& y& z& w\\ \end{matrix} \right] \left[ \begin{matrix} 1& 0& 0& 0\\ 0& 1& 0& 0\\ 0& 0& 1& 0\\ \varDelta x& \varDelta y& \varDelta z& 1\\ \end{matrix} \right] =\left[ \begin{matrix} x+\varDelta x*w& y+\varDelta y*w& z+\varDelta z*w& w\\ \end{matrix} \right] [xyzw]100Δx010Δy001Δz0001=[x+Δxwy+Δywz+Δzww]
只有当W=1,这个三维坐标转换是等价的,才能保证位移的量是正确的,W=0时,则没有位移

只有当W=1时,三维坐标点转换成四维齐次坐标点才是等价的

坐标系变换和矩阵推导

坐标系变换理解不直观,倾向于101中闫老师所说的理解坐标系的转换通过矩阵进行的线性变换,将A坐标系下的点P,乘上矩阵得出B坐标系下的点P’,以下是抛开常见的变换(如透视投影变换、正交投影变换等)如何得出变换矩阵M,通过矩阵变换(下文着重说明)

已知坐标系A和坐标系B
坐 标 系 B 的 x , y , z 轴 在 坐 标 系 A 下 可 表 示 为 ( u x , u y , v z , 0 ) 坐标系B的x,y,z轴在坐标系A下可表示为(u_{\mathrm{x}},u_{\mathrm{y}},v_{\mathrm{z}},0) BxyzAuxuyvz0

( v x , v y , v z , 0 ) , ( w x , w y , w z , 0 ) ,坐标系B的原点在坐标系A下表示为(Q x , Q y , Q z , 1 ) \left( \mathrm{v}_{\mathrm{x}},\mathrm{v}_{\mathrm{y}},\mathrm{v}_{\mathrm{z}},0 \right) \text{,}\left( \mathrm{w}_{\mathrm{x}},\mathrm{w}_{\mathrm{y}},\mathrm{w}_{\mathrm{z}},0 \right) \text{,坐标系B的原点在坐标系A下表示为(Q}_{\mathrm{x}},\mathrm{Q}_{\mathrm{y}},\mathrm{Q}_{\mathrm{z}},1\text{)} (vx,vy,vz,0)(wx,wy,wz,0),坐标系B的原点在坐标系A下表示为(Qx,Qy,Qz,1

img

则将坐标系B中一点P从坐标系B变换到坐标系A的变换矩阵为:(注意此处的例子是将源坐标系A变换到目标坐标系B下)
M = [ u x u y u z 0 v x v y v z 0 w x w y w z 0 Q x Q y Q z 1 ] \mathrm{M}=\left[ \begin{matrix} u_{\mathrm{x}}& u_{\mathrm{y}}& u_{\mathrm{z}}& 0\\ v_{\mathrm{x}}& v_{\mathrm{y}}& v_{\mathrm{z}}& 0\\ w_{\mathrm{x}}& w_{\mathrm{y}}& w_{\mathrm{z}}& 0\\ Q_{\mathrm{x}}& Q_{\mathrm{y}}& Q_{\mathrm{z}}& 1\\ \end{matrix} \right] M=uxvxwxQxuyvywyQyuzvzwzQz0001
如之前所说,变换过程中点p在空间中的绝对位置没有发生改变,只是参考坐标系发生了改变,从B坐标系变到A坐标系。(缩放,旋转,平移变换只有在同一坐标系下才有意义)

矩阵变换是基于基向量组的结果

  • 矩阵变换之于同一个坐标系,可以理解为坐标系不变,点的位置改变
  • 矩阵变换之于不同坐标系,可以理解为点的绝对位置不变,坐标系改变

[ x ′ y ′ ] = B [ x y ] ⇒ [ x y ] = B − 1 [ x ′ y ′ ] , B = [ b 1 → b 2 → ] ,且 b 1 → , b 2 → 是坐标系 B 的基向量 \left[ \begin{array}{c} x^{'}\\ y^{'}\\ \end{array} \right] =B\left[ \begin{array}{c} x\\ y\\ \end{array} \right] \Rightarrow \left[ \begin{array}{c} x\\ y\\ \end{array} \right] =B^{-1}\left[ \begin{array}{c} x^{'}\\ y^{'}\\ \end{array} \right] \text{,}B=\left[ \begin{matrix} \overrightarrow{b_1}& \overrightarrow{b_2}\\ \end{matrix} \right] \text{,且}\overrightarrow{b_1}\text{,}\overrightarrow{b_2}\text{是坐标系}B\text{的基向量} [xy]=B[xy][xy]=B1[xy]B=[b1 b2 ],且b1 b2 是坐标系B的基向量

其中,矩阵B的各个列向量分别对应B坐标系的各个基向量, [ x y ] { \left[ \begin{array}{c} x\\ y\\ \end{array} \right] } [xy]是向量 O P → { \overrightarrow{OP} } OP 或者说点P在B坐标系的表示, [ x ′ y ′ ] { \left[ \begin{array}{c} x^{'}\\ y^{'}\\ \end{array} \right] } [xy]则是向量 O P → { \overrightarrow{OP} } OP 或者点P在A坐标系中的表示

这里写图片描述

以图中的两个向量 b 1 → { \overrightarrow{b_1} } b1 b 2 → { \overrightarrow{b_2} } b2 为基确定一个坐标系B,显然在B坐标系中 b 1 B → = [ 1 0 ] { \overrightarrow{b_{1B}}=\left[ \begin{array}{c} 1\\ 0\\ \end{array} \right] } b1B =[10] b 2 B → = [ 0 1 ] { \overrightarrow{b_{2B}}=\left[ \begin{array}{c} 0\\ 1\\ \end{array} \right] } b2B =[01],接下来,将 b 1 → { \overrightarrow{b_1} } b1 b 2 → { \overrightarrow{b_2} } b2 定位到A坐标系中,得到 b 1 A → = [ 2 1 ] { \overrightarrow{b_{1A}}=\left[ \begin{array}{c} 2\\ 1\\ \end{array} \right] } b1A =[21] b 2 A → = [ − 1 1 ] { \overrightarrow{b_{2A}}=\left[ \begin{array}{c} -1\\ 1\\ \end{array} \right] } b2A =[11]

∵ O P → = 2 b 1 → + 2 b 2 → { \because \overrightarrow{OP}=2\overrightarrow{b_1}+2\overrightarrow{b_2} } OP =2b1 +2b2

∴ O P → { \therefore \overrightarrow{OP}} OP 在B坐标系中的表示为 [ 2 2 ] { \left[ \begin{array}{c} 2\\ 2\\ \end{array} \right] } [22],现在,将 O P → { \overrightarrow{OP} } OP 用A坐标系描叙:
O P → = 2 b 1 → + 2 b 2 → = 2 b 1 A → + 2 b 2 A → = [ b 1 A → b 2 A → ] [ 2 2 ] = [ 2 4 ] { \overrightarrow{OP}=2\overrightarrow{b_1}+2\overrightarrow{b_2}=2\overrightarrow{b_{1A}}+2\overrightarrow{b_{2A}}=\left[ \begin{matrix} \overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\ \end{matrix} \right] \left[ \begin{array}{c} 2\\ 2\\ \end{array} \right] =\left[ \begin{array}{c} 2\\ 4\\ \end{array} \right] \\ } OP =2b1 +2b2 =2b1A +2b2A =[b1A b2A ][22]=[24]
现在,令矩阵B= [ b 1 A → b 2 A → ] { \left[ \begin{matrix} \overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\ \end{matrix} \right] } [b1A b2A ],P点是用B坐标系表示的任意一点 ( x , y ) (x,y) (x,y)
于是 O P → { \overrightarrow{OP} } OP 在A坐标系中的表示 [ x ′ y ′ ] = B [ x y ] { \left[ \begin{array}{c} ^{x^{'}}\\ y^{'}\\ \end{array} \right] =B\left[ \begin{array}{c} x\\ y\\ \end{array} \right] } [xy]=B[xy],显然,B是可逆的,于是就有了之前的结论
那么在这个例子当中,当我们需要知道某点在转换坐标系后的新坐标时,通过该例子也可以加深印象,比如在B坐标系下有点 Q ( 3 , 4 ) Q(3,4) Q(3,4),即 O Q → = ( 3 , 4 ) \overrightarrow{OQ}=(3,4) OQ =(3,4),跟据刚才的例子可以看出它转换在A坐标系下的点
O Q → = 2 b 1 → + 2 b 2 → = 2 b 1 A → + 2 b 2 A → = [ b 1 A → b 2 A → ] [ 3 4 ] = [ 2 − 1 1 1 ] [ 5 4 ] = [ 6 9 ] \overrightarrow{OQ}=2\overrightarrow{b_1}+2\overrightarrow{b_2}=2\overrightarrow{b_{1A}}+2\overrightarrow{b_{2A}}=\left[ \begin{matrix} \overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\ \end{matrix} \right] \left[ \begin{array}{c} 3\\ 4\\ \end{array} \right] =\left[ \begin{matrix} 2& -1\\ 1& 1\\ \end{matrix} \right] \left[ \begin{array}{c} 5\\ 4\\ \end{array} \right] =\left[ \begin{array}{c} 6\\ 9\\ \end{array} \right] OQ =2b1 +2b2 =2b1A +2b2A =[b1A b2A ][34]=[2111][54]=[69]

即转换到A坐标系下的点 Q ′ Q^{'} Q的坐标为 Q ′ ( 6 , 9 ) Q^{'}(6,9) Q(6,9)

虽然这里的讨论是基于二维的,但是,结论可以扩展到任意维度

阐述结论:

将B坐标系的基向量定位到A坐标系,然后将定位之后的基向量作为矩阵B的列向量,用矩阵B对B坐标系中的点P的坐标进行矩阵变换,将得到点P在A坐标系中的坐标。这个过程,就是从坐标系 B到坐标系A的一个追溯过程

View/Camera Transformation

先将相机移到原点,然后进行分别对坐标轴进行旋转,用矩阵表示则是 M v i e w = R v i e w T v i e w M_{view}=R_{view}T_{view} Mview=RviewTview

  • 将相机移回原点

T v i e w = [ 1 0 0 − x e 0 1 0 − y e 0 0 1 − z e 0 0 0 1 ] T_{view}=\left[ \begin{matrix} 1& 0& 0& -x_e\\ 0& 1& 0& -y_e\\ 0& 0& 1& -z_e\\ 0& 0& 0& 1\\ \end{matrix} \right] Tview=100001000010xeyeze1

  • R o t a t e    g    t o    − Z , t    t o    Y , ( g × t )    T o    X Rotate\,\,g\,\,to\,\,-Z, t\,\,to\,\,Y, \left( g×t \right) \,\,To\,\,X RotategtoZ,ttoY,(g×t)ToX
    g是相机看的方向(lookAt),t是相机向上的方向(Up),也就是相机的-Z轴和Y轴,两个向量叉积就是另一个坐标轴

R v i e w − 1 = [ x g ^ × t ^ x t x − g 0 y g ^ × t ^ y t y − g 0 z g ^ × t ^ z t z − g 0 0 0 0 1 ] R_{view}^{-1}=\left[ \begin{matrix} x_{\widehat{g}×\widehat{t}}& x_t& x_{-g}& 0\\ y_{\widehat{g}×\widehat{t}}& y_t& y_{-g}& 0\\ z_{\widehat{g}×\widehat{t}}& z_t& z_{-g}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right] Rview1=xg ×t yg ×t zg ×t 0xtytzt0xgygzg00001

旋转矩阵是正交矩阵,所以旋转矩阵的逆就是旋转矩阵的转置

R v i e w = [ x g ^ × t ^ y g ^ × t ^ z g ^ × t ^ 0 x t y t y t 0 x − g y − g z − g 0 0 0 0 1 ] R_{view}^{}=\left[ \begin{matrix} x_{\widehat{g}×\widehat{t}}& y_{\widehat{g}×\widehat{t}}& z_{\widehat{g}×\widehat{t}}& 0\\ x_t& y_t& y_t& 0\\ x_{-g}& y_{-g}& z_{-g}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right] Rview=xg ×t xtxg0yg ×t ytyg0zg ×t ytzg00001

正交投影矩阵

无论是正交投影还是透视投影,都是要将x、y、z移到-1到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 ) M_{ortho}=\left( \begin{matrix} \frac{2}{r-l}& 0& 0& 0\\ 0& \frac{2}{t-b}& 0& 0\\ 0& 0& \frac{2}{n-f}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right) \left( \begin{matrix} 1& 0& 0& -\frac{r+l}{2}\\ 0& 1& 0& -\frac{t+b}{2}\\ 0& 0& 1& -\frac{n+f}{2}\\ 0& 0& 0& 1\\ \end{matrix} \right) Mortho=rl20000tb20000nf2000011000010000102r+l2t+b2n+f1

透视投影矩阵推导

首先先将frustum 转变为cuboid(n -> n,f -> f)( M p e r s p − > o r t h o M_{persp->ortho} Mpersp>ortho)
然后再做正交投影

整个投影变换包括两部分

  • v = P ( 矩 阵 ) ∗ p v = P(矩阵)*p v=Pp
  • v = v v w = v p z v=\frac{v}{v_w}=\frac{v}{pz} v=vwv=pzv透视除法


以上大概推出等式这一步,接下来用公式展示更为直观
( 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 z ∗ a s p e c t ∗ tan ⁡ ( f o v 2 ) y z ∗ t a n ( f o v 2 ) z ‘ ’ 1 ) \left( \begin{matrix} m00& m01& m02& m03\\ m10& m11& m12& m13\\ m20& m21& m22& m23\\ m30& m31& m32& m33\\ \end{matrix} \right) \left( \begin{array}{c} x\\ y\\ z\\ 1\\ \end{array} \right) =\left( \begin{array}{c} \frac{x}{z*aspect*\tan \left( \frac{fov}{2} \right)}\\ \frac{y}{z*tan\left( \frac{fov}{2} \right)}\\ z^{‘’}\\ 1\\ \end{array} \right) m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33xyz1=zaspecttan(2fov)xztan(2fov)yz1

m 00 ∗ x + m 01 ∗ y + m 02 ∗ z + m 03 = x z ∗ a s p e c t ∗ tan ⁡ ( f o v 2 ) m00*x+m01*y+m02*z+m03=\frac{x}{z*aspect*\tan \left( \frac{fov}{2} \right)} m00x+m01y+m02z+m03=zaspecttan(2fov)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 ∗ tan ⁡ ( f o v 2 ) y tan ⁡ ( f o v 2 ) z ∗ z ′ ′ z ) \left( \begin{matrix} m00& m01& m02& m03\\ m10& m11& m12& m13\\ m20& m21& m22& m23\\ m30& m31& m32& m33\\ \end{matrix} \right) *\left( \begin{array}{c} x\\ y\\ z\\ 1\\ \end{array} \right) =\left( \begin{array}{c} \frac{x}{aspect*\tan \left( \frac{fov}{2} \right)}\\ \frac{y}{\tan \left( \frac{fov}{2} \right)}\\ z*z^{ {'}{'}}\\ z\\ \end{array} \right) m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33xyz1=aspecttan(2fov)xtan(2fov)yzzz

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

m 22 ∗ z + m 23 =    z ∗ z ′ ′ ⇒ m 22 + m 23 z = z ′ ′ m22*z+m23 =\,\,z*z^{ {'}{'}} \\ \Rightarrow m22+\frac{m23}{z}=z^{ {'}{'}} m22z+m23=zzm22+zm23=z

因为z=zNear时,z’’=-1;z=zFar时,z’’=1所以有以下等式
m 22 + m 23 z N e a r = − 1 m 22 + m 23 z F a r = 1 m22+\frac{m23}{zNear}=-1 \\ m22+\frac{m23}{zFar}=1 m22+zNearm23=1m22+zFarm23=1
联立求得:
m 22 = − z F a r − z N e a r z N e a r − z F a r m 23 = 2 ∗ z F a r ∗ z N e a r z N e a r − z F a r m22=\frac{-zFar-zNear}{zNear-zFar} \\ m23=\frac{2*zFar*zNear}{zNear-zFar} m22=zNearzFarzFarzNearm23=zNearzFar2zFarzNear
最后求得投影矩阵为
( 1 a s p e c t ∗ tan ⁡ ( f o v 2 ) 0 0 0 0 1 tan ⁡ ( f o v 2 ) 0 0 0 0 − z F a r − z N e a r z N e a r − z F a r 2 ∗ z N e a r ∗ z F a r z N e a r − z F a r 0 0 1 0 ) \left( \begin{matrix} \frac{1}{aspect*\tan \left( \frac{fov}{2} \right)}& 0& 0& 0\\ 0& \frac{1}{\tan \left( \frac{fov}{2} \right)}& 0& 0\\ 0& 0& \frac{-zFar-zNear}{zNear-zFar}& \frac{2*zNear*zFar}{zNear-zFar}\\ 0& 0& 1& 0\\ \end{matrix} \right) aspecttan(2fov)10000tan(2fov)10000zNearzFarzFarzNear100zNearzFar2zNearzFar0
将这样得矩阵乘以视锥体内的一个顶点坐标,得到一个新的向量,再将这个向量的每个分量除以第四个分量(此步骤也被称为透视除法)(w),这样就可以得到顶点映射到规则立方观察体后的新的坐标

注意:z坐标的映射方式的获得,最后我们是为了方便矩阵乘法的操作方向求得了z坐标与cvv中的z坐标的映射方式:
m 22 + m 23 z = z ′ ′ m22+\frac{m23}{z}=z^{ {'}{'}} m22+zm23=z
此时的映射并不是线性的,当z越大时,z的变化对z’'的扰动越小

Canonical Cube to Screen

  • Irrelevant to z
  • Transform in xy plane : [-1, 1] to [0, width] × [0, height]
  • Viewport transform matrix:

视口矩阵
M v i e w p o r t = [ w i d t h 2 0 0 w i d t h 2 0 h e i g h t 2 0 h e i g h t 2 0 0 1 0 0 0 0 1 ] M_{viewport}=\left[ \begin{matrix} \frac{width}{2}& 0& 0& \frac{width}{2}\\ 0& \frac{height}{2}& 0& \frac{height}{2}\\ 0& 0& 1& 0\\ 0& 0& 0& 1\\ \end{matrix} \right] Mviewport=2width00002height0000102width2height01

深度z的计算

前言
3D光栅化发生在图元被变换到Screen space之后,因为这里的Screen space与2D的Screen Space完全一致,所以2D的光栅化算法在这里依然适用。

然而由于图元经过了投影变换,且投影变换为非线性变换,所以不能用简单的线性插值获取fragment的属性

投影变换不会保持相对距离不变性

如上图所示,view space中的线段v0v1上两点 p 0 ( p 0 x , p 0 y , p 0 z , 1 ) p0\left(p0_x,p0_y,p0_z,1\right) p0(p0x,p0y,p0z,1) p 1 ( p 1 x , p 1 y , p 1 z , 1 ) { p1\left( p1_x,p1_y,p1_z,1 \right) } p1(p1x,p1y,p1z,1)在near plane上的投影为点 s 0 ( s 0 x , s 0 y ) { s0\left( s0_x,s0_y \right) } s0(s0x,s0y) s 1 ( s 1 x , s 1 y ) { s1\left( s1_x,s1_y \right) } s1(s1x,s1y) p 0 { p0 } p0 p 1 p1 p1中间一点 v ( v x , v y , v z , 1 ) {v(v_x,v_y,v_z,1)} v(vx,vy,vz,1)在near plane上的投影为点 q ( q x , q y ) q(q_x,q_y) q(qx,qy)。从图中可以看出点v到p0,p1的距离比值与点q到s0,s1的距离比值完全不同,投影变换不保持距离不变。

为了执行z-buffer算法,需要通过点q获取到v的深度值(z)
v v v的深度值可以通过如下方法插值得到:

v z = 1 c p 1 z + ( 1 − c ) p 0 z v_z=\frac{1}{\frac{c}{p1_z}+\frac{\left( 1-c \right)}{p0_z}} vz=p1zc+p0z(1c)1

以下是推导的过程:

手写版:

文字版:
由于点 q q q为点 v v v在near plane上的投影,因此点 q q q与点 v v v的关系为:

  • q x = v x ⋅ n e a r v z q_x=\frac{v_x·near}{v_z} qx=vzvxnear
    v v v位于 p 0 p 1 p0p1 p0p1之间,则
  • v z = p 0 z + t ⋅ ( p 1 z − p 0 z ) = v x ⋅ n e a r q x v_z=p0_{z}+t·(p1_z-p0_z)=\frac{v_x·near}{q_x} vz=p0z+t(p1zp0z)=qxvxnear
    由点 v v v p 0 p0 p0 p 1 p1 p1之间,点 q q q s 0 s0 s0 s 1 s1 s1之间则有
  • v x = p 0 x ⋅ ( 1 − t ) + p 1 x ⋅ t = p 0 x + t ⋅ ( p 1 x − p 0 x ) v_x=p0_{x}·(1-t)+p1_{x}·t=p0_{x}+t·(p1_{x}-p0_{x}) vx=p0x(1t)+p1xt=p0x+t(p1xp0x)
  • q x = s 0 x ⋅ ( 1 − c ) + s 1 x ⋅ c = s 0 x + c ⋅ ( s 1 x − s 0 x ) q_x=s0_{x}·(1-c)+s1_{x}·c=s0_{x}+c·(s1_{x}-s0_{x}) qx=s0x(1c)+s1xc=s0x+c(s1xs0x)
    代入式(1)可得
    v z = v x ⋅ n e a r q x = ( p 0 x + t ⋅ ( p 1 x − p 0 x ) ) ⋅ n e a r s 0 x + c ⋅ ( s 1 x − s 0 x ) v_z=\frac{v_x·near}{q_x}=\frac{(p0_x+t·(p1_x-p0_x))·near}{s0_x+c·(s1_x-s0_x)} vz=qxvxnear=s0x+c(s1xs0x)(p0x+t(p1xp0x))near式(2)
    又s0和s1分别为p0和p1在near plane上的投影,则:
  • s 0 x = p 0 x ⋅ n e a r p 1 z s0_x=\frac{p0_x·near}{p1_z} s0x=p1zp0xnear
  • s 1 x = p 1 x ⋅ n e a r p 1 z s1_x=\frac{p1_x·near}{p1_z} s1x=p1zp1xnear
    代入式(2)可得:

v z = ( p 0 x ⋅ s 0 x n e a r + t ⋅ ( p 1 x ⋅ s 1 x n e a r − p 0 x ⋅ s 0 x n e a r ) ) ⋅ n e a r s 0 x + c ⋅ ( s 1 x − s 0 x ) v_z=\frac{\left( \frac{p0_x·s0_x}{near}+t·\left( \frac{p1_x·s1_x}{near}-\frac{p0_x·s0_x}{near} \right) \right) ·near}{s0_x+c·\left( s1_x-s0_x \right)} vz=s0x+c(s1xs0x)(nearp0xs0x+t(nearp1xs1xnearp0xs0x))near

v z = ( p 0 x ⋅ s 0 x n e a r + t ⋅ ( p 1 x ⋅ s 1 x n e a r − p 0 x ⋅ s 0 x n e a r ) ) ⋅ n e a r s 0 x + c ⋅ ( s 1 x − s 0 x ) v z = ( p 0 x ⋅ s 0 x + t ⋅ ( p 1 x ⋅ s 1 x − p 0 x ⋅ s 0 x ) ) s 0 x + c ⋅ ( s 1 x − s 0 x ) p 0 z + t ⋅ ( p 1 z − p 0 z ) = ( p 0 x ⋅ s 0 x + t ⋅ ( p 1 x ⋅ s 1 x − p 0 x ⋅ s 0 x ) ) s 0 x + c ⋅ ( s 1 x − s 0 x ) ( p 0 z + t ⋅ ( p 1 z − p 0 z ) ) ⋅ ( s 0 x + c ⋅ ( s 1 x − s 0 x ) ) = p 0 x ⋅ s 0 x + t ⋅ ( p 1 x ⋅ s 1 x − p 0 x ⋅ s 0 x ) p 0 z ⋅ s 0 x + p 0 z ⋅ c ⋅ ( s 1 x − s 0 x ) + t ⋅ ( p 1 z − p 0 z ) ⋅ s 0 x + t ⋅ c ⋅ ( p 1 z − p 0 z ) ⋅ ( s 1 x − s 0 x ) = p 0 x ⋅ s 0 x + t ⋅ ( p 1 x ⋅ s 1 x − p 0 x ⋅ s 0 x ) v_z=\frac{\left( \frac{p0_x·s0_x}{near}+t·\left( \frac{p1_x·s1_x}{near}-\frac{p0_x·s0_x}{near} \right) \right) ·near}{s0_x+c·\left( s1_x-s0_x \right)} \\ v_z=\frac{\left( p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right) \right)}{s0_x+c·\left( s1_x-s0_x \right)} \\ p0_z+t·\left( p1_z-p0_z \right) =\frac{\left( p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right) \right)}{s0_x+c·\left( s1_x-s0_x \right)} \\ \left( p0_z+t·\left( p1_z-p0_z \right) \right) ·\left( s0_x+c·\left( s1_x-s0_x \right) \right) =p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right) \\ p0_z·s0_x+p0_z·c·\left( s1_x-s0_x \right) +t·\left( p1_z-p0_z \right) ·s0_x+t·c·\left( p1_z-p0_z \right) ·\left( s1_x-s0_x \right) =p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right) vz=s0x+c(s1xs0x)(nearp0xs0x+t(nearp1xs1xnearp0xs0x))nearvz=s0x+c(s1xs0x)(p0xs0x+t(p1xs1xp0xs0x))p0z+t(p1zp0z)=s0x+c(s1xs0x)(p0xs0x+t(p1xs1xp0xs0x))(p0z+t(p1zp0z))(s0x+c(s1xs0x))=p0xs0x+t(p1xs1xp0xs0x)p0zs0x+p0zc(s1xs0x)+t(p1zp0z)s0x+tc(p1zp0z)(s1xs0x)=p0xs0x+t(p1xs1xp0xs0x)

化简得:
t ⋅ ( p 1 z − c ⋅ ( p 1 z − p 0 z ) ) = c ⋅ p 0 z t·\left( p1_z-c·\left( p1_z-p0_z \right) \right) =c·p0_z t(p1zc(p1zp0z))=cp0z
则:
t = c ⋅ p 0 z c ⋅ p 0 z + ( 1 − c ) ⋅ p 1 z t=\frac{c·p0_z}{c·p0_z+(1-c)·p1_z} t=cp0z+(1c)p1zcp0z
代入式(1)可得
v z = p 0 z + t ⋅ ( p 1 z − p 0 z ) v_z=p0_z+t·(p1_z-p0_z) vz=p0z+t(p1zp0z)
v z = p 0 z + c ⋅ p 0 z c ⋅ p 0 z + ( 1 − c ) ⋅ p 1 z ⋅ ( p 1 z − p 0 z ) v_z=p0_z+\frac{c·p0_z}{c·p0_z+(1-c)·p1_z}·(p1_z-p0_z) vz=p0z+cp0z+(1c)p1zcp0z(p1zp0z)
v z = 1 c p 1 z + ( 1 − c ) p 0 z v_z=\frac{1}{\frac{c}{p1_z}+\frac{(1-c)}{p0_z}} vz=p1zc+p0z(1c)1

若View Space中三角形 v 0 v 1 v 2 v0v1v2 v0v1v2,变换到Screen Space后为三角形 s 0 s 1 s 2 s0s1s2 s0s1s2 v 0 v 1 v 2 v0v1v2 v0v1v2内一点v在Screen Space的投影点 s 0 s 1 s 2 s0s1s2 s0s1s2内的点 q q q,对三角形 s 0 s 1 s 2 s0s1s2 s0s1s2内的点(fragment) q q q,可以通过如下方法取得fragment q q q在View Space中对应的深度值:

q . z = v . z = 1 λ 0 v 0. z + λ 1 v 1. z + λ 2 v 2. z q.z=v.z=\frac{1}{\frac{\lambda0}{v0.z}+\frac{\lambda1}{v1.z}+\frac{\lambda2}{v2.z}} q.z=v.z=v0.zλ0+v1.zλ1+v2.zλ21

λ 0 , λ 1 , λ 2 \lambda0,\lambda1,\lambda2 λ0,λ1,λ2为点p在三角形 s 0 s 1 s 2 s0s1s2 s0s1s2内的重心坐标
引入结论:
对Screen Space三角形 s 0 , s 1 , s 2 s0,s1,s2 s0,s1,s2内一点 p p p的任意属性插值的公式为:
A t r i b u t e ( p ) = z ⋅ ( λ 0 ⋅ A t r i b u t e ( v 0 ) z 0 + λ 1 ⋅ A t r i b u t e ( v 1 ) z 1 + λ 2 ⋅ A t r i b u t e ( v 2 ) z 2 ) Atribute\left( p \right) =z·\left( \frac{\lambda 0·Atribute\left( v0 \right)}{z0}+\frac{\lambda 1·Atribute\left( v1 \right)}{z1}+\frac{\lambda 2·Atribute\left( v2 \right)}{z2} \right) Atribute(p)=z(z0λ0Atribute(v0)+z1λ1Atribute(v1)+z2λ2Atribute(v2))
λ 0 , λ 1 , λ 2 \lambda0,\lambda1,\lambda2 λ0,λ1,λ2为点 p p p的重心坐标, z 0 , z 1 , z 2 , z z0,z1,z2,z z0,z1,z2,z分别为 s 0 , s 1 , s 2 , p s0,s1,s2,p s0,s1,s2,p在view space中对应点的深度值,可以用这个方法插值得到 p p p在NDC Space内对应点的深度值
此处贴一下Games101作业框架中关于深度的计算,与上述公式对应 z = z i n t e r p o l a t e d ∗ w r e c i p r o c a l z = z_interpolated*w_reciprocal z=zinterpolatedwreciprocal

    auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
    float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
    float z_interpolated =
    alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
    z_interpolated *= w_reciprocal;

    if (depth_buf[get_index(x, y)] > z_interpolated) {
    
    
        depth_buf[get_index(x, y)] = z_interpolated;
        Eigen::Vector3f point;
        point << static_cast<float>(x), static_cast<float>(y), z_interpolated;
        set_pixel(point, t.getColor());
    }

罗德里格斯旋转公式

指定任意轴k旋转 α {\alpha} α角得出旋转矩阵
字写得不好,在爬了…
手写版:

文字版:
首先先将 k → \overrightarrow{k} k 处理成单位向量,这点很重要,关乎着下一步等式是否成立,有些博文写这里不需要处理单位向量,这是错的

v → ⋅ k → = ∣ v → ∣ ⋅ ∣ k → ∣ ⋅ cos ⁡ < v → , k → > = ∣ v → ∣ ⋅ cos ⁡ < v → , k → > \overrightarrow{v}·\overrightarrow{k}=|\overrightarrow{v}|·|\overrightarrow{k}|·\cos <\overrightarrow{v}\text{,}\overrightarrow{k}>=|\overrightarrow{v}|·\cos <\overrightarrow{v}\text{,}\overrightarrow{k}> v k =v k cos<v ,k >=v cos<v ,k >
可得
v ∣ ∣ → = ∣ v → ∣ ⋅ cos ⁡ < v → , k → > ⋅ k → v → = v ⊥ → + v ∣ ∣ → v ⊥ → = v → − v ∣ ∣ → = v → − ( v → ⋅ k → ) k → \overrightarrow{v_{||}}=|\overrightarrow{v}|·\cos <\overrightarrow{v},\overrightarrow{k}>·\overrightarrow{k} \\ \overrightarrow{v}=\overrightarrow{v_{\bot}}+\overrightarrow{v_{||}} \\ \overrightarrow{v_{\bot}}=\overrightarrow{v}-\overrightarrow{v_{||}}=\overrightarrow{v}-\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} v =v cos<v ,k >k v =v +v v =v v =v (v k )k
k → \overrightarrow{k} k 做旋转时,向下做垂线,可看作底部经过了类似半圆的旋转
要求得 v r o t → = v ∣ ∣ → + v r o t ⊥ → \overrightarrow{v_{rot}}=\overrightarrow{v_{||}}+\overrightarrow{v_{rot\bot}} vrot =v +vrot ,将 v r o t ⊥ → \overrightarrow{v_{rot\bot}} vrot 作正交分解有 v r o t ⊥ → = a → + b → { \overrightarrow{v_{rot\bot}}=\overrightarrow{a}+\overrightarrow{b} } vrot =a +b ,易得 ∣ w → ∣ = ∣ v ⊥ → ∣ { |\overrightarrow{w}|=|\overrightarrow{v_{\bot}}| } w =v ,则有 w → = k → × v ⊥ → = k → × [ v → − v ∣ ∣ → ] = k → × v → − k → × v ∣ ∣ → = k → × v → − 0 = k → × v → { \overrightarrow{w}=\overrightarrow{k}×\overrightarrow{v_{\bot}}=\overrightarrow{k}×\left[ \overrightarrow{v}-\overrightarrow{v_{||}} \right] =\overrightarrow{k}×\overrightarrow{v}-\overrightarrow{k}×\overrightarrow{v_{||}}=\overrightarrow{k}×\overrightarrow{v}-0=\overrightarrow{k}×\overrightarrow{v} } w =k ×v =k ×[v v ]=k ×v k ×v =k ×v 0=k ×v
接下来求 a → { \overrightarrow{a} } a b → { \overrightarrow{b} } b

∣ a → ∣ = ∣ v r o t ⊥ → ∣ ⋅ cos ⁡ ( θ − 90 ) = ∣ v r o t ⊥ → ∣ ⋅ sin ⁡ ( θ ) a → = w → ∣ w → ∣ ⋅ ∣ a → ∣ = w → ∣ v r o t ⊥ → ∣ ⋅ ∣ v r o t ⊥ → ∣ ⋅ sin ⁡ ( θ ) = w → ⋅ sin ⁡ ( θ ) |\overrightarrow{a}|=|\overrightarrow{v_{rot\bot}}|·\cos \left( \theta -90 \right) =|\overrightarrow{v_{rot\bot}}|·\sin \left( \theta \right) \\ \overrightarrow{a}=\frac{\overrightarrow{w}}{|\overrightarrow{w}|}·|\overrightarrow{a}|=\frac{\overrightarrow{w}}{|\overrightarrow{v_{rot\bot}}|}·|\overrightarrow{v_{rot\bot}}|·\sin \left( \theta \right) =\overrightarrow{w}·\sin \left( \theta \right) a =vrot cos(θ90)=vrot sin(θ)a =w w a =vrot w vrot sin(θ)=w sin(θ)

∣ b → ∣ = ∣ v r o t ⊥ → ∣ ⋅ cos ⁡ ( 180 − θ ) = ∣ v r o t ⊥ → ∣ ⋅ cos ⁡ ( θ ) b → = v ⊥ → ∣ v ⊥ → ∣ ⋅ ∣ b → ∣ = v ⊥ → ∣ v ⊥ → ∣ ⋅ ∣ v r o t ⊥ → ∣ ⋅ cos ⁡ ( θ ) = v ⊥ → ⋅ cos ⁡ ( θ )    注意 ∣ v ⊥ → ∣ = ∣ v r o t ⊥ → ∣ |\overrightarrow{b}|=|\overrightarrow{v_{rot\bot}}|·\cos \left( 180-\theta \right) =|\overrightarrow{v_{rot\bot}}|·\cos \left( \theta \right) \\ \overrightarrow{b}=\frac{\overrightarrow{v_{\bot}}}{|\overrightarrow{v_{\bot}}|}·|\overrightarrow{b}|=\frac{\overrightarrow{v_{\bot}}}{|\overrightarrow{v_{\bot}}|}·|\overrightarrow{v_{rot\bot}}|·\cos \left( \theta \right) =\overrightarrow{v_{\bot}}·\cos \left( \theta \right) \,\, \text{注意}|\overrightarrow{v_{\bot}}|=|\overrightarrow{v_{rot\bot}}| b =vrot cos(180θ)=vrot cos(θ)b =v v b =v v vrot cos(θ)=v cos(θ)注意v =vrot

v r o t ⊥ → = a → + b → = w → ⋅ sin ⁡ ( θ ) + v ⊥ → ⋅ cos ⁡ ( θ ) = sin ⁡ ( θ ) ⋅ ( k → × v → ) + cos ⁡ ( θ ) ( v → − ( v → ⋅ k → ) k → ) v r o t → = v ∣ ∣ → + v r o t ⊥ → = ( v → ⋅ k → ) k → + sin ⁡ ( θ ) ⋅ ( k → × v → ) + cos ⁡ ( θ ) ( v → − ( v → ⋅ k → ) k → ) = cos ⁡ ( θ ) v → + ( 1 − cos ⁡ ( θ ) ( v → ⋅ k → ) k → ) + sin ⁡ ( θ ) ⋅ ( k → × v → ) \overrightarrow{v_{rot\bot}}=\overrightarrow{a}+\overrightarrow{b}=\overrightarrow{w}·\sin \left( \theta \right) +\overrightarrow{v_{\bot}}·\cos \left( \theta \right) =\sin \left( \theta \right) ·\left( \overrightarrow{k}×\overrightarrow{v} \right) +\cos \left( \theta \right) \left( \overrightarrow{v}-\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} \right) \\ \overrightarrow{v_{rot}}=\overrightarrow{v_{||}}+\overrightarrow{v_{rot\bot}}=\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k}+\sin \left( \theta \right) ·\left( \overrightarrow{k}×\overrightarrow{v} \right) +\cos \left( \theta \right) \left( \overrightarrow{v}-\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} \right) \\ =\cos \left( \theta \right) \overrightarrow{v}+\left( 1-\cos \left( \theta \right) \left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} \right) +\sin \left( \theta \right) ·\left( \overrightarrow{k}×\overrightarrow{v} \right) vrot =a +b =w sin(θ)+v cos(θ)=sin(θ)(k ×v )+cos(θ)(v (v k )k )vrot =v +vrot =(v k )k +sin(θ)(k ×v )+cos(θ)(v (v k )k )=cos(θ)v +(1cos(θ)(v k )k )+sin(θ)(k ×v )

k → { \overrightarrow{k} } k v → { \overrightarrow{v} } v 分别写为列向量
k → = ( k x k y k z ) \overrightarrow{k}=\left( \begin{array}{c} k_x\\ k_y\\ k_z\\ \end{array} \right) k =kxkykz

v → = ( v x v y v z ) \overrightarrow{v}=\left( \begin{array}{c} v_x\\ v_y\\ v_z\\ \end{array} \right) v =vxvyvz

v r o t → = R ⋅ v → { \overrightarrow{v_{rot}}=R·\overrightarrow{v} } vrot =Rv
两个式子
( v → ⋅ k → ) k → = k → ( v → ⋅ k → ) = k → ( k T → ⋅ v → ) \left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k}=\overrightarrow{k}\left( \overrightarrow{v}·\overrightarrow{k} \right) =\overrightarrow{k}\left( \overrightarrow{k^T}·\overrightarrow{v} \right) (v k )k =k (v k )=k (kT v )
k → × v → = [ k y v z − k z v y k z v x − k x v z k x v y − k y v x ] = [ 0 − k z k y k z 0 − k x − k y k x 0 ] [ v x v y v z ] \overrightarrow{k}×\overrightarrow{v}=\left[ \begin{array}{c} k_yv_z-k_zv_y\\ k_zv_x-k_xv_z\\ k_xv_y-k_yv_x\\ \end{array} \right] =\left[ \begin{matrix} 0& -k_z& k_y\\ k_z& 0& -k_x\\ -k_y& k_x& 0\\ \end{matrix} \right] \left[ \begin{array}{c} v_x\\ v_y\\ v_z\\ \end{array} \right] k ×v =kyvzkzvykzvxkxvzkxvykyvx=0kzkykz0kxkykx0vxvyvz
结合以上两个式子可得,其中 I I I为3×3的单位矩阵
R = I cos ⁡ ( θ ) + ( 1 − cos ⁡ ( θ ) ) ( k x k y k z ) ( k x k y k z ) + sin ⁡ ( θ ) ( 0 − k z k y k z 0 − k x − k y k x 0 )    R=I\cos \left( \theta \right) +\left( 1-\cos \left( \theta \right) \right) \left( \begin{array}{c} k_x\\ k_y\\ k_z\\ \end{array} \right) \left( \begin{matrix} k_x& k_y& k_z\\ \end{matrix} \right) +\sin \left( \theta \right) \left( \begin{matrix} 0& -k_z& k_y\\ k_z& 0& -k_x\\ -k_y& k_x& 0\\ \end{matrix} \right) \,\, R=Icos(θ)+(1cos(θ))kxkykz(kxkykz)+sin(θ)0kzkykz0kxkykx0
以下是比较通用的表示方式
R ( n , α ) = cos ⁡ ( α ) I + ( 1 − cos ⁡ ( α ) ) n n T + sin ⁡ ( α ) ( 0 − n z n y n z 0 − n x − n y n x 0 ) R\left( n,\alpha \right) =\cos \left( \alpha \right) I+\left( 1-\cos \left( \alpha \right) \right) nn^T+\sin \left( \alpha \right) \left( \begin{matrix} 0& -n_z& n_y\\ n_z& 0& -n_x\\ -n_y& n_x& 0\\ \end{matrix} \right) R(n,α)=cos(α)I+(1cos(α))nnT+sin(α)0nznynz0nxnynx0

部分引用的博文

https://blog.csdn.net/unclerunning/article/details/70948696#%E9%BD%90%E6%AC%A1%E5%9D%90%E6%A0%87%E7%B3%BB%E4%B8%8E%E5%B9%B3%E7%A7%BB

https://zhuanlan.zhihu.com/p/45757899

猜你喜欢

转载自blog.csdn.net/lr_shadow/article/details/118190108