计算机图形:观察变换(Viewing Transformation)

几何体变换到屏幕坐标一般步骤:

img

观察变换

观察变换(View Transformation):指3D->2D的变换,包括相机变换、投影变换及规范化、视口变换. 主要任务:将3D位置(世界坐标\((x,y,z)\))映射到2D图像坐标(pixel).

而模型变换指设置对象位置、大小、方向.

观察变换包含的3部分:

  • 相机变换(Camera Transformation)或眼睛变换(Eye Transformation): 将对象从世界坐标(世界空间)转换到相机的观察坐标(相机空间). 取决于相机位置和方向/姿势.
  • 投影变换(Orthographic Projection Transformation): 将相机空间的投影点转换到观察平面(投影平面),进行规范化和裁剪.
  • 视口变换(Viewport Transformation)或窗口变换(Windowing Transformation): 将单位图像矩形映射到屏幕空间中的像素矩形.

前面计算机图形:mvp变换(模型、视图、投影变换)讲过MVP变换,包括模型变换、相机变换(视图变换)、投影变换及规范化. 本文主要讲视口变换.

从观察变换角度,物体由原始坐标变换到屏幕空间的示意图:

img

视口变换

几何体经投影变换及规范化后,得到规范化观察体,如何得到屏幕上的图像?

规范化观察体(NDC view volume):将投影观察体中所有点变换成矩形平行管道观察体中的位置,该观察体是坐标范围\((x,y,z)\in [-1,1]^3\)的立方体.

tips: 规范化观察体中物体用NDC坐标(Normalized Device Coordinates, 标准设备坐标)描述.

规范化立方体示意图:

img

视口变换(Viewport Transformation):将规范化观察体中所有点变换到屏幕上.

规范化观察体与屏幕映射关系:

\[\begin{aligned} x=-1&\xrightarrow{}屏幕左边, x=+1\xrightarrow{}屏幕右边\\ y=-1&\xrightarrow{}屏幕下边, y=+1\xrightarrow{}屏幕上边\\ z=-1&\xrightarrow{}深度缓冲0, z=+1\xrightarrow{}深度缓冲1 \end{aligned} \]

考虑像素宽度

对于拥有\(n_x\times n_y\)像素的屏幕,需将NDC的矩形\([-1,1]^2\)映射到屏幕矩形\([-0.5,n_x-0.5]\times [-0.5,n_y-0.5]\)上. 其中,视口左下角像素坐标\((0, 0)\)

e.g. \(4\times 3\)像素屏幕坐标示意图:

img

可以看到,像素中心点位于整数坐标值,而像素边界却并没有.

要将规范化观察体上矩形的任一点\((x_{NDC},y_{NDC})\)变换到屏幕\((x_{screen}\\y_{screen})\)位置,可根据点占的横纵比例不变原则计算:

\[\begin{aligned} \frac{x_{screen}-(-0.5)}{n_x-0.5-(-0.5)}&=\frac{x_{NDC}-(-1)}{1-(-1)}\\ \frac{y_{screen}-(-0.5)}{n_y-0.5-(-0.5)}&=\frac{y_{NDC}-(-1)}{1-(-1)} \end{aligned} \]

于是,可得到视口变换:

\[\begin{pmatrix} x_{screen}\\y_{screen}\\1 \end{pmatrix} =\begin{pmatrix} \frac{n_x}{2} & 0 & \frac{n_x-1}{2}\\ 0 & \frac{n_y}{2} & \frac{n_y-1}{2}\\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x_{NDC}\\y_{NDC}\\1 \end{pmatrix} \]

3D空间下,视口变换矩阵:

\[M_{vp}=\begin{pmatrix} \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{pmatrix} \]

如果视口左下角坐标不是\((0,0)\), 而是\((x_0,y_0)\),矩形宽高\(n_x\times n_y\). 那么,需将NDC空间\([-1,1]^2\)映射到屏幕空间\([x_0-0.5,x_0+n_x-0.5]\times [y_0-0.5, y_0+n_y-0.5]\)

则视口变换为:

\[\begin{aligned} \frac{x_{screen}-(x_0-0.5)}{n_x} &= \frac{x_{NDC}-(-1)}{1-(-1)}\\ \frac{y_{screen}-(y_0-0.5)}{n_y} &= \frac{y_{NDC}-(-1)}{1-(-1)}\\ \implies \begin{pmatrix} x_{screen}\\ y_{screen}\\ 1 \end{pmatrix} &= \begin{pmatrix} \frac{n_x}{2} & 0 & x_0 + \frac{n_x - 1}{2}\\ 0 & \frac{n_y}{2} & y_0 + \frac{n_y - 1}{2}\\ 0 & 0 & 1\\ \end{pmatrix} \begin{pmatrix} x_{NDC}\\y_{NDC}\\1 \end{pmatrix} \end{aligned} \]

不考虑像素速宽度

如果不考虑像素宽度,即认为像素上所有细分点与像素中心在同一屏幕坐标,那么,需将NDC空间\([-1,1]^2\)映射到屏幕空间\([x_0,x_0+n_x]\times [y_0,y_0+n_y]\)

则视口变换为:

\[\begin{aligned} \frac{x_{screen}-x_0}{x_0+n_x-x_0}&=\frac{x_{NDC}-(-1)}{1-(-1)}\\ \frac{y_{screen}-y_0}{y_0+n_y-y_0}&=\frac{y_{NDC}-(-1)}{1-(-1)}\\ \implies \begin{pmatrix} x_{screen}\\y_{screen}\\1 \end{pmatrix} &=\begin{pmatrix} \frac{n_x}{2} & 0 & x_0+\frac{n_x}{2}\\ 0 & \frac{n_y}{2} & y_0+\frac{n_y}{2}\\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x_{NDC}\\y_{NDC}\\1 \end{pmatrix} \end{aligned} \]

其中:

  • \((x_0,y_0)\):视口左下角在屏幕中的像素坐标;
  • \(n_x,n_y\):视口的宽度和高度(像素);

考虑屏幕深度

不考虑像素宽度情况下,如果我们考虑屏幕的深度值,那么,观察变换又该是什么呢?

\(depth_{near}, depth_{far}\) 分别是屏幕的近平面和远平面的深度值.

\[z:[-1,1]\ in\ NDC\to depth_{near}, depth_{far}\ in \ Screen \ Space \]

\[\frac{z_{NDC}-(-1)}{1-(-1)} = \frac{z_{screen}-depth_{near}}{z_{far}-z_{near}}\\ z_{screen} = \frac{depth_{far}-depth_{near}}{2}z_{NDC}+\frac{depth_{far}+depth_{near}}{2} \]

\[\begin{pmatrix} x_{screen}\\y_{screen}\\z_{screen}\\1 \end{pmatrix} =\begin{pmatrix} \frac{n_x}{2} & 0 & 0 & x_0+\frac{n_x}{2}\\ 0 & \frac{n_y}{2} & 0 & y_0+\frac{n_y}{2}\\ 0 & 0 & \frac{depth_{far}-depth_{near}}{2} & \frac{depth_{far}+depth_{near}}{2}\\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x_{NDC}\\y_{NDC}\\z_{NDC} \\1 \end{pmatrix} \]

参考

[1] Marschner S , Shirley P .Fundamentals of computer graphics. 4th edition.[J].World Scientific Publishers Singapore, 2009, 9(1):29-51.DOI:doi:10.1021/i160033a008.

[2] 计算机图形:mvp变换(模型、视图、投影变换)

posted @ 2025-02-12 20:44  明明1109  阅读(128)  评论(0)    收藏  举报