回顾Games101 chapter 1 - 6
前言
本文只写回顾后重新加深认识的知识
透视除法的意义
经过MVP矩阵之后,将模型空间下某点的坐标,转换成了裁剪空间下的坐标,此时因为裁剪空间的范围是 x ∈ [ − W / 2 , W / 2 ] x∈[-W/2,W/2] x∈[−W/2,W/2]和 y ∈ [ − H / 2 , H / 2 ] y∈[-H/2,H/2] y∈[−H/2,H/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 −1≤2⋅w(pzpx⋅near)≤1−1≤2⋅h(pzpy⋅near)≤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+Δx∗wy+Δy∗wz+Δz∗ww]
只有当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) 坐标系B的x,y,z轴在坐标系A下可表示为(ux,uy,vz,0)
( 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)
则将坐标系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{的基向量} [x′y′]=B[xy]⇒[xy]=B−1[x′y′],B=[b1b2],且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] } [x′y′]则是向量 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=[b1Ab2A][22]=[24]
现在,令矩阵B= [ b 1 A → b 2 A → ] { \left[ \begin{matrix} \overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\ \end{matrix} \right] } [b1Ab2A],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] } [x′y′]=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=[b1Ab2A][34]=[21−11][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=⎣⎢⎢⎡100001000010−xe−ye−ze1⎦⎥⎥⎤
- 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 Rotategto−Z,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] Rview−1=⎣⎢⎢⎡xg ×t yg ×t zg ×t 0xtytzt0x−gy−gz−g00001⎦⎥⎥⎤
旋转矩阵是正交矩阵,所以旋转矩阵的逆就是旋转矩阵的转置
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 xtx−g0yg ×t yty−g0zg ×t ytz−g00001⎦⎥⎥⎤
正交投影矩阵
无论是正交投影还是透视投影,都是要将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=⎝⎜⎜⎛r−l20000t−b20000n−f200001⎠⎟⎟⎞⎝⎜⎜⎛100001000010−2r+l−2t+b−2n+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=P(矩阵)∗p
- 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) ⎝⎜⎜⎛m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33⎠⎟⎟⎞⎝⎜⎜⎛xyz1⎠⎟⎟⎞=⎝⎜⎜⎜⎛z∗aspect∗tan(2fov)xz∗tan(2fov)yz‘’1⎠⎟⎟⎟⎞
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)} m00∗x+m01∗y+m02∗z+m03=z∗aspect∗tan(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) ⎝⎜⎜⎛m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33⎠⎟⎟⎞∗⎝⎜⎜⎛xyz1⎠⎟⎟⎞=⎝⎜⎜⎜⎛aspect∗tan(2fov)xtan(2fov)yz∗z′′z⎠⎟⎟⎟⎞
所以求得矩阵为
( 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) ⎝⎜⎜⎜⎛aspect∗tan(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^{ {'}{'}} m22∗z+m23=z∗z′′⇒m22+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=zNear−zFar−zFar−zNearm23=zNear−zFar2∗zFar∗zNear
最后求得投影矩阵为
( 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) ⎝⎜⎜⎜⎛aspect∗tan(2fov)10000tan(2fov)10000zNear−zFar−zFar−zNear100zNear−zFar2∗zNear∗zFar0⎠⎟⎟⎟⎞
将这样得矩阵乘以视锥体内的一个顶点坐标,得到一个新的向量,再将这个向量的每个分量除以第四个分量(此步骤也被称为透视除法)(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(1−c)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=vzvx⋅near
且 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⋅(p1z−p0z)=qxvx⋅near
由点 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⋅(1−t)+p1x⋅t=p0x+t⋅(p1x−p0x)
- 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⋅(1−c)+s1x⋅c=s0x+c⋅(s1x−s0x)
代入式(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=qxvx⋅near=s0x+c⋅(s1x−s0x)(p0x+t⋅(p1x−p0x))⋅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=p1zp0x⋅near
- s 1 x = p 1 x ⋅ n e a r p 1 z s1_x=\frac{p1_x·near}{p1_z} s1x=p1zp1x⋅near
代入式(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⋅(s1x−s0x)(nearp0x⋅s0x+t⋅(nearp1x⋅s1x−nearp0x⋅s0x))⋅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⋅(s1x−s0x)(nearp0x⋅s0x+t⋅(nearp1x⋅s1x−nearp0x⋅s0x))⋅nearvz=s0x+c⋅(s1x−s0x)(p0x⋅s0x+t⋅(p1x⋅s1x−p0x⋅s0x))p0z+t⋅(p1z−p0z)=s0x+c⋅(s1x−s0x)(p0x⋅s0x+t⋅(p1x⋅s1x−p0x⋅s0x))(p0z+t⋅(p1z−p0z))⋅(s0x+c⋅(s1x−s0x))=p0x⋅s0x+t⋅(p1x⋅s1x−p0x⋅s0x)p0z⋅s0x+p0z⋅c⋅(s1x−s0x)+t⋅(p1z−p0z)⋅s0x+t⋅c⋅(p1z−p0z)⋅(s1x−s0x)=p0x⋅s0x+t⋅(p1x⋅s1x−p0x⋅s0x)
化简得:
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⋅(p1z−c⋅(p1z−p0z))=c⋅p0z
则:
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=c⋅p0z+(1−c)⋅p1zc⋅p0z
代入式(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⋅(p1z−p0z)
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+c⋅p0z+(1−c)⋅p1zc⋅p0z⋅(p1z−p0z)
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(1−c)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λ0⋅Atribute(v0)+z1λ1⋅Atribute(v1)+z2λ2⋅Atribute(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=zinterpolated∗wreciprocal
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>⋅kv=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+(1−cos(θ)(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=R⋅v
两个式子
( 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=⎣⎡kyvz−kzvykzvx−kxvzkxvy−kyvx⎦⎤=⎣⎡0kz−ky−kz0kxky−kx0⎦⎤⎣⎡vxvyvz⎦⎤
结合以上两个式子可得,其中 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(θ)+(1−cos(θ))⎝⎛kxkykz⎠⎞(kxkykz)+sin(θ)⎝⎛0kz−ky−kz0kxky−kx0⎠⎞
以下是比较通用的表示方式
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+(1−cos(α))nnT+sin(α)⎝⎛0nz−ny−nz0nxny−nx0⎠⎞
部分引用的博文
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