《Fundamentals of Computer Graphics》第八章 视图
<h1 id="开篇">开篇</h1><p> 上一章主要讲了使用变换矩阵和改变坐标系统。有一个次重要的一点就是使用矩阵在物体的三维位置和物体在二维视图的位置之间进行变换。其中三维到二维的映射叫做<strong>视图变换</strong>(<strong>Viewing Transformation</strong>),这种映射在物体顺序渲染中很重要,因为这种渲染方式需要我们快速地为场景中的每个物体找到它在图像空间的位置。第四章讲的光线追踪,涵盖了透视视图和正交视图,以及如何为给定的视图生成光线,这章讲的就是这个过程的反向过程,即如何使用矩阵变换来表达任意平行或透视视图。<br>
要注意的是把点从世界映射到图像上只能很好地进行<strong>线框</strong>(<strong>Wireframe</strong>)渲染,也就是只能看到被绘制的物体的边缘部分,如下图所示。而且更近的物体可能不会遮蔽更远的物体,就像光线追踪器需要为每个视线找到最近的交点一样,一个能显示物体实体表面的基于物体顺序的渲染器,需要在影响相同像素着色的所有表面中挑选出最近的表面。在这章,我们假设模型只由三维线段组成,后面的章节将会讨论渲染实体表面所需要的机制。<br>
<img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250607233209409-1461477467.png"></p>
<h1 id="视图变换viewing-transformation">视图变换(Viewing Transformation)</h1>
<p> 视图变换的作用就是把规范坐标系统的<span class="math inline">\((x,y,z)\)</span>三维位置映射到以像素为单位的图像中,不过这稍微有点复杂,因为依赖于相机的位置和朝向还有投影类型、视场、图像的分辨率。和其它的很多的复杂变换一样,我们最好把视图变换拆解为几个更简单的变换,许多图形系统通过一序列的三个变换来达到视图变换。</p>
<ul>
<li>
<p>一个<strong>相机变换</strong>或者<strong>眼变换</strong>:它是一个刚体变换,通过把一个有着便捷朝向的相机放到原点来做到,只取决于位置、朝向或者相机的姿态。</p>
</li>
<li>
<p>一个<strong>投影变换</strong>:它会变换在相机空间中的点并且让可见的点都落在<span class="math inline">\(x,y \in [-1,1]\)</span>的归一化坐标空间内,它只取决于投影的类型。</p>
</li>
<li>
<p>一个<strong>视口变换</strong>(<strong>Viewport Transformation</strong>)或<strong>窗口变换</strong>(<strong>Windowing Transformation</strong>):它把单位的图像矩形映射到期望的像素坐标矩形内,它只取决于输出图像的大小和位置。<br>
为了更好的描述如下图所示的过程的几个阶段,我们给予一些坐标系统名字。<br>
<img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250608001317896-420952342.png"></p>
</li>
</ul>
<p>相机变换把规范坐标系内的坐标转换到<strong>相机空间</strong>(<strong>Camera Space</strong>)中,投影变换把相机空间中可见的点变换到<strong>规范视图体</strong>(<strong>Canonical View Volume</strong>)内,视口变换在最后把规范视图体映射到<strong>屏幕空间</strong>(<strong>Screen Space</strong>)。这几个单独的变换都很简单,下面先从正交投影开始,后续会覆盖支持透视投影所需要的改变。</p>
<h2 id="视口变换viewport-transformation">视口变换(Viewport Transformation)</h2>
<p> 我们假设被看到的物体最后都在规范视图体内,而且期望有个正交相机朝着<span class="math inline">\(+z\)</span>方向观察。规范视图体是个立方体,它包含着笛卡尔坐标在<span class="math inline">\([-1,1]\)</span>之内的所有三维点,也就是<span class="math inline">\((x,y,z) \in [-1,1]^3\)</span>,如下图所示。我们把<span class="math inline">\(x=-1\)</span>投影到屏幕左边,把<span class="math inline">\(x=1\)</span>投影到屏幕右边,把<span class="math inline">\(y=-1\)</span>投影到屏幕底边,把<span class="math inline">\(y=1\)</span>投影到屏幕顶边。如果屏幕左下角的像素的中心坐标为<span class="math inline">\((0,0)\)</span>且像素边长为一单位,那么对于一个每排<span class="math inline">\(n_x\)</span>像素和每列<span class="math inline">\(n_y\)</span>像素的屏幕,我们得把正方形<span class="math inline">\([-1,1]^2\)</span>映射到矩形<span class="math inline">\([-0.5,n_x-0.5] \times [-0.5,n_y-0.5]\)</span>。<br>
<img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250624134734338-1319610247.png"></p>
<p> 出于初学的目的,我们先假设所有被绘制的线段在被变换后都完全处于规范视图体内。不过,当我们之后讨论<strong>裁剪</strong>(<strong>Clipping</strong>)时会取消这个限制。因为视口变换只是映射矩形,所以视口变换可以如下所示</p>
<p></p><div class="math display">\[\begin{bmatrix} x_{screen} \\ y_{screen} \\ 1 \end{bmatrix} = \begin{bmatrix} \frac{n_x}{2} & 0 & \frac{n_x-1}{2} \\ 0 & \frac{n_y}{2} & \frac{n_y-1}{2} \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_{canonical} \\ y_{canonical} \\ 1 \end{bmatrix}
\]</div><p></p><p>要注意的是式子中的矩阵忽视了<span class="math inline">\(z\)</span>坐标,因为点沿着投影方向的距离和它所影响的像素位置无关。在正式称之为<strong>视口矩阵</strong>(<strong>Viewport Matrix</strong>)前,我们增加一行和一列来支持<span class="math inline">\(z\)</span>坐标,</p>
<p></p><div class="math display">\[M_\mathrm{vp}=\begin{bmatrix} \frac{n_x}{2} & 0 & 0 & \frac{n_x-1}{2} \\ 0 & \frac{n_y}{2} & 0 & \frac{n_y-1}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
\]</div><p></p><p>当前这个章节不需要这些,不过当我们想让更近的表面遮蔽更远的表面时会用到<span class="math inline">\(z\)</span>值。</p>
<h2 id="正交投影变换the-orthographic-projection-transformation">正交投影变换(The Orthographic Projection Transformation)</h2>
<p> 当然了,被看到物体一般都不会直接处于规范视图体内,我们需要把位于相机空间的视图体内的物体变换到规范视图体中。我们首先确定相机空间中的相机的观察方向为<span class="math inline">\(-z\)</span>方向并且以<span class="math inline">\(+y\)</span>为向上方向,对于正交投影来说,相机空间内的视图体为<span class="math inline">\( \times \times \)</span>,我们称这个视图体为<strong>正交视图体</strong>(<strong>Orthographic View Volume</strong>),它的包围平面为:</p>
<p></p><div class="math display">\[\begin{align*}
x&=l\equiv左平面\\
x&=r\equiv右平面\\
y&=b\equiv底平面\\
y&=t\equiv顶平面\\
z&=n\equiv近平面\\
z&=f\equiv远平面
\end{align*}
\]</div><p></p><p><img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250608193008310-1874743260.png"><br>
由于我们确定了观察方向为<span class="math inline">\(-z\)</span>方向并且以<span class="math inline">\(+y\)</span>为向上方向,这会导致<span class="math inline">\(n>f\)</span>,可能看起来怪怪的。不过考虑到整个正交视图体都有负<span class="math inline">\(z\)</span>值,<span class="math inline">\(z=n\)</span>的近平面有着更大的<span class="math inline">\(z\)</span>值因此离观察者最近,下图是一个正交视图体的直观展示。<br>
<img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250608195628383-1692221126.png"><br>
从正交视图体到规范视图体的变换其实是另外一种窗口变换,因此正交投影变换矩阵为</p>
<p></p><div class="math display">\[\mathbf{M}_\mathrm{orth} = \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix}
\]</div><p></p><h2 id="相机变换the-camera-transformation">相机变换(The Camera Transformation)</h2>
<p> 我们通常可能想在世界空间中的任意位置摆放有着任意朝向的相机,通过相机变换我们就能把位于世界空间中的物体变换到相机空间中,为此我们需要</p>
<ul>
<li><span class="math inline">\(\mathbf{e}\)</span>:眼睛位置</li>
<li><span class="math inline">\(\mathbf{g}\)</span>:视线方向</li>
<li><span class="math inline">\(\mathbf{t}\)</span>:向上向量(辅助向量)<br>
<img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250608202310945-1216729742.png"></li>
</ul>
<p>要注意的是这里的向上向量<span class="math inline">\(\mathbf{t}\)</span>只是一个辅助向量,它会把观察者的头分成两半,而且对于站在地面上的人来说会指向天空。有了这些信息,我们就能构建一个坐标系统,以<span class="math inline">\(\mathbf{e}\)</span>为原点,以<span class="math inline">\(\mathbf{uvw}\)</span>为基,如上图所示。利用第二章提到的知识,我们可以这样得到基向量</p>
<p></p><div class="math display">\[\begin{align*}
\mathbf{w} &= - \frac{\mathbf{g}}{||\mathbf{g}||} \\
\mathbf{u} &= \frac{\mathbf{t} \times \mathbf{w}}{||\mathbf{t} \times \mathbf{w}||} \\
\mathbf{v} &= \mathbf{w} \times \mathbf{u}
\end{align*}
\]</div><p></p><p>得到标准正交基后,接下来我们利用上一章提到的坐标系统之间转换的知识,把规范坐标系内的物体变换到相机空间中,变换矩阵为</p>
<p></p><div class="math display">\[\mathbf{M}_\mathrm{cam}=\begin{bmatrix} \mathbf{u} & \mathbf{v} & \mathbf{w} & \mathbf{e} \\ 0 & 0 & 0 & 1 \end{bmatrix}^{-1} = \begin{bmatrix} x_u & y_u & z_u & 0 \\ x_v & y_v & z_v & 0 \\ x_w & y_w & z_w & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & -x_e \\ 0 & 1 & 0 & -y_e \\ 0 & 0 & 1 & -z_e \\ 0 & 0 & 0 & 1 \end{bmatrix}
\]</div><p></p><p>使用这个矩阵变换后,相机会位于相机空间中的原点,并且以<span class="math inline">\(+y\)</span>为向上方向,向<span class="math inline">\(-z\)</span>方向观察,这就对应了上一部分开头对相机做的假设。这里你可能会问为什么会朝着<span class="math inline">\(-z\)</span>观察,这是因为<span class="math inline">\(\mathbf{w} = - \mathbf{g}/||\mathbf{g}||\)</span>,所以观察方向<span class="math inline">\(\vec{g}\)</span>在相机空间中为<span class="math inline">\(-z\)</span>。综上,用于把规范坐标系内的物体投影到屏幕空间的矩阵<span class="math inline">\(\mathbf{M}\)</span>为</p>
<p></p><div class="math display">\[\mathbf{M}=\mathbf{M}_\mathrm{vp}\mathbf{M}_\mathrm{orth}\mathbf{M}_\mathrm{cam}
\]</div><p></p><h1 id="透视投影变换">透视投影变换</h1>
<p> 透视投影变换和正交投影变换一样,都是要把相机空间内的视图体变换到规范视图体,不过透视投影变换的视图体和正交投影变换的六面体不一样。下图是这两者的区别<br>
<img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250609192811462-1399244691.png"><br>
我们称透视投影变换的视图体为<strong>视锥台</strong>(<strong>View Frustum</strong>),它是一个视锥体被近平面截去后所获得的一个棱台。在这里,我们假设视锥台是对称的,接下来要做的就是把这种视锥台映射映射到规范视图体<span class="math inline">\([-1,1]^3\)</span>。<br>
对于视锥台内某点的变换,可能很难想出来。但是我们可以这么想,对于从相机空间的原点出发,并且经过视锥台的任意光线来说,这上面的点在屏幕空间中都会有相同的<span class="math inline">\(x\)</span>坐标和<span class="math inline">\(y\)</span>坐标。于是第一步就是找到光线和<strong>相机空间中的图像平面</strong>的交点。<br>
对于上述这种光线,我们可以把它看作是位置关于<span class="math inline">\(z\)</span>坐标的函数,即</p>
<p></p><div class="math display">\[f(z)=(Az,Bz,z)
\]</div><p></p><p>假设相机空间中的图像平面离相机空间的原点的距离为<span class="math inline">\(d\)</span>,那么光线与图像平面的交点为</p>
<p></p><div class="math display">\[f(-d)=(-Ad,-Bd,-d)
\]</div><p></p><p>我们令交点为<span class="math inline">\((x_1,y_1,-d)\)</span>。获得与图像平面的交点后,接着就能通过一次平移变化把交点的<span class="math inline">\(x\)</span>、<span class="math inline">\(y\)</span>坐标变换到屏幕空间中的<span class="math inline">\(x\)</span>、<span class="math inline">\(y\)</span>坐标。又因为从屏幕空间变换到规范视图体只是一次逆的平移变换加上一次逆的缩放变换,于是这个时候能得出一个结论:我们只需要一次缩放变换就能把交点的<span class="math inline">\(x\)</span>、<span class="math inline">\(y\)</span>坐标变换到在规范视图体内的<span class="math inline">\(x\)</span>、<span class="math inline">\(y\)</span>坐标。假设被渲染的图像的宽和高分别为<span class="math inline">\(w\)</span>和<span class="math inline">\(h\)</span>,那么交点的<span class="math inline">\(x\)</span>、<span class="math inline">\(y\)</span>坐标的变换公式分别为</p>
<p></p><div class="math display">\[x^{\prime}_1 = \frac{x_1}{w/2}
\]</div><p></p><p></p><div class="math display">\[y^{\prime}_1 = \frac{y_1}{h/2}
\]</div><p></p><p>那么对于光线上任意一点<span class="math inline">\((x_2,y_2,z_2)\)</span>,我们先把它线性缩放到图像平面上,缩放因子为<span class="math inline">\(-d/z_2\)</span>,接着再进行线性变换。于是有如下公式</p>
<p></p><div class="math display">\[x^{\prime}_2 = \frac{-d \, x_2}{(w/2)z_2} = \frac{-2d}{w} \frac{x_2}{z_2}
\]</div><p></p><p></p><div class="math display">\[y^{\prime}_2 = \frac{-d \, y_2}{(h/2)z_2} = \frac{-2d}{h} \frac{y_2}{z_2}
\]</div><p></p><p>在实践中,我们通常不会用到图像平面相关的信息,取而代之的是和近平面或FOV相关的信息。假设近平面的坐标为<span class="math inline">\(z=n\)</span>,且它的左边和右边分别有<span class="math inline">\(x=l\)</span>和<span class="math inline">\(x=r\)</span>,它的底边和顶边分别有<span class="math inline">\(y=b\)</span>和<span class="math inline">\(y=t\)</span>。利用相似关系我们可以得到</p>
<p></p><div class="math display">\[\frac{2n}{r-l} = \frac{-2d}{w}
\]</div><p></p><p></p><div class="math display">\[\frac{2n}{t-b} = \frac{-2d}{h}
\]</div><p></p><p>因此,对于视锥台内任意一点<span class="math inline">\(\mathbf{p}(x_p,y_p,z_p)\)</span>来说,它的<span class="math inline">\(x\)</span>坐标和<span class="math inline">\(y\)</span>坐标的变换公式分别为</p>
<p></p><div class="math display">\[x^{\prime}_p=\frac{2n}{r-l} \frac{x_p}{z_p}
\]</div><p></p><p></p><div class="math display">\[y^{\prime}_p=\frac{2n}{t-b} \frac{y_p}{z_p}
\]</div><p></p><p>到这里就完成了<span class="math inline">\(x_p\)</span>和<span class="math inline">\(y_p\)</span>的变换,这个时候你可能会想当然地认为<span class="math inline">\(z_p\)</span>的变换会利用近平面和远平面进行线性变换,且公式如下</p>
<p></p><div class="math display">\[z^{\prime}_p = 2\frac{z_p-n}{f-n} -1
\]</div><p></p><p>然而实际情况却不是这样,通过翻阅用于不同<strong>图形API</strong>的数学库,你会发现这些数学库用到的透视投影矩阵都会非线性地映射<span class="math inline">\(z\)</span>坐标到<span class="math inline">\(\)</span>。<strong>GLM</strong>中的右手透视投影<code>perspectiveRH_NO</code>用到的变换如下</p>
<p></p><div class="math display">\[z^\prime = \frac{f+n}{f-n}-\frac{2fn}{f-n} \frac{1}{z}
\]</div><p></p><p>当<span class="math inline">\(z=n\)</span>时,<span class="math inline">\(z^\prime=-1\)</span>。当<span class="math inline">\(z=f\)</span>时,<span class="math inline">\(z^\prime=1\)</span>。而<strong>DirectXMath</strong>中的右手透视投影<code>XMMatrixPerspectiveFovRH</code>用到的变换如下</p>
<p></p><div class="math display">\[z^\prime = \frac{f}{f-n}-\frac{fn}{f-n} \frac{1}{z}
\]</div><p></p><p>当<span class="math inline">\(z=n\)</span>时,<span class="math inline">\(z^\prime=0\)</span>。当<span class="math inline">\(z=f\)</span>时,<span class="math inline">\(z^\prime=1\)</span>。这里要说明一下,因为Direct3D用到的规范视图体的<span class="math inline">\(z\in \)</span>,所以配套的DirectXMath数学库使用的是这种变换。这种非线性映射实际上是为了更好地分配精度,来让近处的深度精度更高,从而不易观察出瑕疵。而对于我们的情况来说,可以直接使用GLM中的<code>perspectiveRH_NO</code>函数所用到的变换。因此<span class="math inline">\(x_p\)</span>、<span class="math inline">\(y_p\)</span>、<span class="math inline">\(z_p\)</span>的变换分别为</p>
<p></p><div class="math display">\[\begin{align*}
x^{\prime}_p&=\frac{2n}{r-l} \frac{x_p}{z_p} \\
y^{\prime}_p&=\frac{2n}{t-b} \frac{y_p}{z_p} \\
z^{\prime}_p&=\frac{f+n}{f-n}-\frac{2fn}{f-n} \frac{1}{z_p} = \left(\frac{(f+n)z_p}{f-n}-\frac{2fn}{f-n}\right) \frac{1}{z_p}
\end{align*}
\]</div><p></p><p>观察上三式会发现这三个分量的变换都得除以<span class="math inline">\(z_p\)</span>,但是我们的<span class="math inline">\(4\times4\)</span>矩阵不能直接完成这件事。于是这个时候得利用齐次坐标,我们先赋予<span class="math inline">\(\mathbf{p}\)</span>齐次坐标到<span class="math inline">\(\mathbf{p}(x_p,y_p,z_p,1)\)</span>。对于以上三个分量的变换,我们先不考虑<span class="math inline">\(1/z_p\)</span>对变换的影响,即为每个分量的变换计算除了<span class="math inline">\(1/z_p\)</span>之外的部分,另外我们还让变换后的齐次坐标<span class="math inline">\(w^{new}_p\)</span>等于<span class="math inline">\(z_p\)</span>,这样就把<span class="math inline">\(\mathbf{p}(x_p,y_p,z_p,1)\)</span>变换到了四维空间内,这个变换如下所示</p>
<p></p><div class="math display">\[ \mathbf{p}^{new} =\begin{bmatrix} \frac{2n}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2n}{t-b} & 0 & 0 \\ 0 & 0 & \frac{f+n}{f-n} & -\frac{2fn}{f-n} \\ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} x_p \\ y_p \\ z_p \\ 1 \end{bmatrix}
\]</div><p></p><p>我们称等式右侧的矩阵为透视投影变换矩阵,变换后的<span class="math inline">\(\mathbf{p}^{new}\)</span>的四个分量分别为</p>
<p></p><div class="math display">\[\begin{align*}
x^{new}_p&=\frac{2n}{r-l} x_p \\
y^{new}_p&=\frac{2n}{t-b} y_p \\
z^{new}_p&=\frac{(f+n)z_p}{f-n}-\frac{2fn}{f-n} \\
w^{new}_p&=z_p
\end{align*}
\]</div><p></p><p>最后我们利用<span class="math inline">\(w^{new}_p\)</span>进行一次透视除法也称为<strong>齐次化</strong>(<strong>Homogenize</strong>),从而得到<span class="math inline">\(\mathbf{p}^{\prime}=\mathbf{p}^{new}/w^{new}_p\)</span>。</p>
<h1 id="透视变换的一些属性some-properties-of-the-perspective-transform">透视变换的一些属性(Some Properties of the Perspective Transform)</h1>
<p> 透视变换的一个重要的属性就是直线被变换后依旧是直线,平面被变换后依旧是平面。下面我们证明这一点,现有相机空间内的两点<span class="math inline">\(\mathbf{q}\)</span>、<span class="math inline">\(\mathbf{Q}\)</span>,我们用参数<span class="math inline">\(t\in\)</span>描述线段<span class="math inline">\(\mathbf{qQ}\)</span></p>
<p></p><div class="math display">\[\mathbf{q}+t(\mathbf{Q}-\mathbf{q})
\]</div><p></p><p>令这两个点在四维空间内的坐标分别为<span class="math inline">\(\mathbf{r}\)</span>和<span class="math inline">\(\mathbf{R}\)</span>,使用透视矩阵<span class="math inline">\(\mathbf{M}\)</span>变换可得</p>
<p></p><div class="math display">\[\mathbf{Mq}+t(\mathbf{MQ}-\mathbf{Mq})\equiv\mathbf{r}+t(\mathbf{R}-\mathbf{r})
\]</div><p></p><p>齐次化后的三维线段为</p>
<p></p><div class="math display">\[\frac{\mathbf{r}+t(\mathbf{R}-\mathbf{r})}{w_r+t(w_R-w_r)}
\]</div><p></p><p>经过暴力运算后可重写成</p>
<p></p><div class="math display">\[\frac{\mathbf{r}}{w_r}+f(t)(\frac{\mathbf{R}}{w_R}-\frac{\mathbf{r}}{w_r})
\]</div><p></p><p>而<span class="math inline">\(f(t)\)</span>为</p>
<p></p><div class="math display">\[f(t)=\frac{w_Rt}{w_r+t(w_R-w_r)}
\]</div><p></p><h1 id="视场field-of-view">视场(Field-of-View)</h1>
<p> 视场即<strong>FOV</strong>(<strong>Field-of-View</strong>),它是透视投影变换部分提到的边缘视线与观察方向<span class="math inline">\(\vec{g}\)</span>之间的夹角的两倍,我们令它为<span class="math inline">\(\theta\)</span>。之前的部分提到的透视变换矩阵为</p>
<p></p><div class="math display">\[\begin{bmatrix} \frac{2n}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2n}{t-b} & 0 & 0 \\ 0 & 0 & \frac{f+n}{f-n} & -\frac{2fn}{f-n} \\ 0 & 0 & 1 & 0 \end{bmatrix}
\]</div><p></p><p><span class="math inline">\(y\)</span>的缩放因子为</p>
<p></p><div class="math display">\[\frac{2n}{t-b}
\]</div><p></p><p><img src="https://img2023.cnblogs.com/blog/2774734/202506/2774734-20250610215747771-1978110529.png"></p>
<p>由上图易得<span class="math inline">\(\theta\)</span>和它的关系为</p>
<p></p><div class="math display">\[\tan\frac{\theta}{2}=\frac{t-b}{2|n|}
\]</div><p></p><p>因此我们可以通过视场<span class="math inline">\(\theta\)</span>、近平面和远平面的<span class="math inline">\(z\)</span>值的绝对值<span class="math inline">\(|n|\)</span>和<span class="math inline">\(|f|\)</span>、输出图像的宽高比<span class="math inline">\(\mathrm{AspectRatio}\)</span>得到透视变换矩阵。下面分别列举GLM(<code>perspectiveRH_NO</code>)和DirectXMath(<code>XMMatrixPerspectiveFovRH</code>)用到的右手透视变换矩阵<span class="math inline">\(\mathbf{M}\)</span>。</p>
<p></p><div class="math display">\[\mathbf{M}_{\mathrm{GLM}} = \begin{bmatrix} \frac{1}{\tan(\theta/2)\mathrm{AspectRatio}} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\theta/2)} & 0 & 0 \\ 0 & 0 & -\frac{|f|+|n|}{|f|-|n|} & -\frac{2|f||n|}{|f|-|n|} \\ 0 & 0 & -1 & 0 \end{bmatrix}
\]</div><p></p><p></p><div class="math display">\[\mathbf{M}_{\mathrm{DXMATH}} = \begin{bmatrix} \frac{1}{\tan(\theta/2)\mathrm{AspectRatio}} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\theta/2)} & 0 & 0 \\ 0 & 0 & \frac{|f|}{|n|-|f|} & \frac{|f||n|}{|n|-|f|} \\ 0 & 0 & -1 & 0 \end{bmatrix}
\]</div><p></p>
</div>
<div id="MySignature" role="contentinfo">
<p>本文来自博客园,作者:TiredInkRaven,转载请注明原文链接:https://www.cnblogs.com/TiredInkRaven/p/18917149</p><br><br>
来源:https://www.cnblogs.com/TiredInkRaven/p/18917149
頁:
[1]