观察矩阵(View Matrix)、投影矩阵(Projection Matrix)、视口矩阵(Window Matrix)及VPM矩阵及它们之间的关系

      V表示摄像机的观察矩阵(View Matrix),它的作用是把对象从世界坐标系变换到摄像机坐标系。因此,对于世界坐标系下的坐标值worldCoord(x0, y0, z0),如果希望使用观察矩阵VM将其变换为摄像机坐标系下的坐标值localCoord(x’, y’, z’),则有:

localCoord = worldCoord * VM

此外,观察矩阵可理解为“摄像机在世界坐标系下的位姿矩阵的逆矩阵”,也可理解为"世界坐标系在摄像机坐标系下的位姿矩阵。因此Camera 类也专门提供了getInverseViewMatrix 这样一个函数,它的实际意义是表示摄像机在世界坐标系下的位置;而Camera 类的getViewMatrix函数则表示世界坐标系下的某个物体的位姿矩阵变换到以摄像机坐标系为基准下的矩阵。这个有点绕,具体参见如下博文:

浅谈在操控器类中,为何要通过osgGA::CameraManipulator的逆矩阵改变视点位置

        P 表示投影矩阵(Projection Matrix),当我们使用 setProjectionMatrixAsPerspective 之类的函数设置摄像机的投影矩阵时,我们相当于创建了一个视截锥体,并尝试把包含在其中的场景对象投影到镜头平面上来。如果投影矩阵为PM,而得到的投影坐标为projCoord(x”, y”, z”)的话,那么:

projCoord = localCoord * PM

      W表示视口矩阵(Window Matrix),它负责把投影坐标变换到指定的二维视口(viewport)中去, 对于视口矩阵WM,通过下面的公式可以得到最终的窗口坐标windowCoord(x”', y”', 0):

windowCoord = projCoord * WM

将所有的公式整合之后,得到:

windowCoord = worldCoord * VM * PM * WM

而这个所谓的窗口坐标windowCoord,实际上也就是世界坐标系下的坐标值worldCoord 在指定的摄像机视口中(也就是我们的屏幕上)对应的平面位置。怎么样,不知不觉中,我 们已经实现了gluProject函数所完成的功能了。记:

VPW =  VM * PM * WM

则:

windowCoord = worldCoord * VPM

 对上式左右两边乘以VPM的逆,如下:

即反转这三个步骤就可以得到视口中指定位置所对应的世界坐标了(也就是gluUnProject的工作)即:

参考资料

【1】:王锐 .《最长的一帧》 

<think>我们正在讨论矩阵Viewport Matrix)的相关信息。矩阵在计算机图形学中扮演着关键角色,特别是在渲染管线的最后阶段,用于将归一化设备坐标(Normalized Device Coordinates, NDC)转换为屏幕坐标(Screen Coordinates)。根据引用[4]的描述,变换是将NDC坐标转换为屏幕坐标的过程,这主要通过线性映射实现,同时考虑坐标系统的方向和的偏移。 ### 1. 矩阵的定义 矩阵是一个变换矩阵,用于将顶点从NDC空间(通常是一个立方体,范围为[-1,1]³或[0,1]³)映射到屏幕空间(即窗坐标系)。这个变换通常包括缩放和平移操作。在OpenGL中,NDC空间的范围是[-1,1]³,而在DirectX中,NDC空间的范围可能是[0,1]³(取决于API和投影矩阵的设置)。矩阵需要根据屏幕的尺寸(宽度和高度)以及的位置(通常以左下角为原点)来构建。 ### 2. 矩阵的作用 矩阵的主要作用是将归一化设备坐标(NDC)转换为屏幕坐标。这个过程是渲染管线的最后一步,确保3D场景中的物体正确地显示在屏幕的指定区域()上。具体包括: - **缩放**:将NDC的坐标范围映射到屏幕的像素尺寸。 - **平移**:根据在屏幕上的位置调整原点。 - **深度调整**:将NDC的深度范围(通常是[-1,1]或[0,1])映射到深度缓冲区的范围(通常是[0,1])。 ### 3. 矩阵的计算方法 矩阵通常由以下步骤构造: #### a. 确定参数 - 左下角在屏幕上的位置:$(x_v, y_v)$ - 的宽度:$w_v$ - 的高度:$h_v$ - 深度缓冲区范围:$[minDepth, maxDepth]$(通常为[0,1]) #### b. 缩放和平移 假设NDC空间为[-1,1]³(OpenGL风格): - 将x坐标从[-1,1]映射到$[x_v, x_v + w_v]$: - 缩放因子:$w_v/2$ - 平移量:$x_v + w_v/2$ - 将y坐标从[-1,1]映射到$[y_v, y_v + h_v]$: - 注意:屏幕坐标通常以左上角为原点,而NDC以左下角为原点,因此y轴需要翻转(乘以-1)并平移$y_v + h_v$。但具体取决于API和坐标系约定。 - 将z坐标从[-1,1]映射到$[minDepth, maxDepth]$: - 缩放因子:$(maxDepth - minDepth)/2$ - 平移量:$minDepth + (maxDepth - minDepth)/2$ #### c. 矩阵的构造 因此,矩阵可以表示为缩放矩阵和平移矩阵的乘积: $$ M_{\text{viewport}} = \begin{bmatrix} \frac{w_v}{2} & 0 & 0 & x_v + \frac{w_v}{2} \\ 0 & -\frac{h_v}{2} & 0 & y_v + \frac{h_v}{2} \\ 0 & 0 & \frac{maxDepth - minDepth}{2} & minDepth + \frac{maxDepth - minDepth}{2} \\ 0 & 0 & 0 & 1 \end{bmatrix} $$ 注意:y坐标缩放中的负号(-h_v/2)是因为屏幕坐标系的y轴通常是向下为正(与NDC的y轴向上为正相反)。如果屏幕坐标系y轴向上为正,则使用正号。 ### 4. 实际应用示例 在引用[2]中,我们看到一个设置的代码示例(虽然是在Vulkan环境下),它设置了的位置和大小,然后结合投影矩阵和模型变换矩阵来渲染2D内容。这里的关键是确保尺寸与投影矩阵匹配,以避免图像拉伸。 ### 5. 与其他变换的关系 变换是渲染管线的最后一步。在此之前,顶点需要经过模型变换、图变换、投影变换(如透投影或正交投影)以及透除法(得到NDC)。引用[3]和[5]提到了投影矩阵的推导,而引用[1]提到了模型图变换。 ### 总结 矩阵是图形渲染管线中不可或缺的一部分,它负责将归一化设备坐标(NDC)映射到屏幕空间。其构造依赖于的位置、尺寸和深度缓冲区的设置。正确设置矩阵可以确保3D场景正确地显示在屏幕的指定区域。 §§相关问题§§ 1. 矩阵在哪些图形API中需要手动设置? 2. 如果屏幕分辨率变化,矩阵应如何调整? 3. 矩阵投影矩阵有什么区别和联系? 4. 在Unity或Unreal引擎中,矩阵是如何处理的? </think>### 矩阵Viewport Matrix)详解 #### **1. 定义** 矩阵是计算机图形学中的一种变换矩阵,负责将**归一化设备坐标(NDC)** 映射到**屏幕坐标(像素坐标)**。其核心功能是将投影变换后的标准化坐标(范围通常为$[-1,1]^3$或$[0,1]^3$)转换为实际渲染窗的像素位置[^4][^2]。 #### **2. 核心作用** - **坐标映射**:将NDC坐标线性映射到屏幕像素坐标系。 - **自适应**:根据窗尺寸动态调整显示比例(如引用[2]中的宽高比计算)。 - **深度校正**:将NDC深度值映射到深度缓冲区范围(通常$[0,1]$)。 - **多支持**:实现分屏渲染时定义不同渲染区域(引用[2]多分割)。 #### **3. 计算公式** 矩阵本质是**缩放矩阵 + 平移矩阵**的组合: $$ M_{\text{viewport}} = \begin{bmatrix} \frac{w}{2} & 0 & 0 & \frac{w}{2} + x_0 \\ 0 & -\frac{h}{2} & 0 & \frac{h}{2} + y_0 \\ 0 & 0 & d_{\text{max}} - d_{\text{min}} & d_{\text{min}} \\ 0 & 0 & 0 & 1 \end{bmatrix} $$ **参数说明**: - $x_0, y_0$:左下角在屏幕中的坐标(像素) - $w, h$:宽度和高度(像素) - $d_{\text{min}}, d_{\text{max}}$:深度缓冲区范围(通常$d_{\text{min}}=0, d_{\text{max}}=1$) #### **4. 计算步骤(以OpenGL为例)** 1. **确定范围**: 设屏幕分辨率$W \times H$,左下角$(x_0, y_0)$,尺寸$w \times h$。 2. **计算缩放比例**: - X方向缩放:$\frac{w}{2}$(NDC的$[-1,1]$映射到$[0,w]$) - Y方向缩放:$-\frac{h}{2}$(负号因屏幕Y轴向下) 3. **计算平移量**: - X平移:$x_0 + \frac{w}{2}$ - Y平移:$y_0 + \frac{h}{2}$ 4. **深度映射**: 将NDC深度$z \in [-1,1]$映射到$[d_{\text{min}}, d_{\text{max}}]$(引用[4])。 #### **5. 与其他变换的关系** - **投影矩阵**:生成NDC坐标(引用[5]透投影矩阵推导)。 - **模型矩阵**:组合物体位置和摄像机角(引用[1])。 - **最终坐标变换流程**: $$ \text{模型坐标} \xrightarrow{M_{\text{model-view}}} \text{相机坐标} \xrightarrow{M_{\text{proj}}}} \text{NDC} \xrightarrow{M_{\text{viewport}}}} \text{屏幕坐标} $$ #### **6. 实际应用示例** 引用[2]的代码展示了矩阵的典型使用场景: ```cpp // 设置矩形 VkViewport viewport{0, 0, (float)windowWidth, (float)windowHeight, 0, 1}; // 构建正交投影矩阵(与尺寸匹配) Mat2D projection = makeOrthographicProjection(-w/2, w/2, -h/2, h/2); // 应用变换 renderer->transform(Mat2D::fromScale(scale)); renderer->transform(projection); ``` 此处通过组合缩放和投影矩阵实现自适应渲染。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值