1.4 MVP矩阵

MVP矩阵代表什么

MVP矩阵分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。

 

我们的顶点坐标起始于局部空间(Local Space),在这里他成为局部坐标(Local Coordinates),它在之后会变为世界坐标(World Coordinates),观察坐标(View Coordinates),裁剪坐标(Clip Coordinates),并最后以屏幕坐标(Screen Coordinates)的形式结束。过程如下图所示

-------------------------------------------参考《Unity Shader入门精要》----------------------------------------

模型空间

模型空间(Model Space),或者说是对象空间(Object Space)、局部空间(Local Space)

模型空间原点和坐标轴通常是由美术人员在建模软件里确定好的,原点通常位于模型的中心。

世界空间

世界空间(World Space)是一个特殊的坐标系,因为他建立了我们所关心的最大空间。通常,我们会把世界空间的原点放置在游戏空间的中心。

将顶点坐标从模型空间变换到世界空间中,这个变换通常叫做模型变换

根据Transform组件上的信息,模型进行了(2,2,2)的缩放,又进行了(0,150,0)的旋转,以及(5,0,25)的平移。注意:这里的变换顺序不能互换。要按照先缩放,再旋转,最后平移,矩阵从右到左依次是缩放——旋转——位移矩阵。因此可以构建出模型变换的变换矩阵:

现在可以对目标物体进行模型变换了:

Pworld:世界空间下的目标点坐标。

Mmodel:模型变换矩阵。

Pmodel:模型空间下的目标点坐标。

也就是说世界空间下目标点位置是(9,4,18.072),注意这里的浮点数都是近似值。实际数值和Unity采用的浮点精度有关。

观察空间

观察空间(View Space)也被称为摄像机空间(Camera Space)。观察空间可以认为是模型空间的一个特例——在所有的模型中一个非常特殊的模型,即摄像机。

在Unity中的观察空间坐标轴选择是:+x轴指向右方,+y指向上方,+z指向的是摄像机后方。这里+z与模型空间和世界空间的+z相反,因为,Unity在模型空间和世界空间选用的是左手坐标系,观察空间使用的是右手坐标系。这是符合OpenGL传统的。

从世界空间变换到观察空间的过程叫做观察变换(View Transform)。

得到顶点在观察空间中的位置有两种方法:

①计算观察空间三个坐标在世界空间下的标识,然后构建出从观察空间到世界空间的变换矩阵,再对该矩阵求逆来得到从世界空间变换到观察空间的变换矩阵。

②想象平移整个观察空间,让摄像机原点位于世界坐标的原点,坐标轴与世界空间中的坐标轴重合即可。

采用第二种方法来计算变换。相机在世界空间中经过缩放->旋转->平移的到最终位置,所以逆变换需要以平移->旋转->缩放的顺序来计算。

由于观察空间是右手坐标系,所以要对z分量进行取反操作。

最后对顶点进行变换。

得到观察空间中目标顶点中的位置——(9, 8.84, -27.31)

裁剪空间

裁剪空间(Clip Space)也被成为齐次裁剪空间,这个用于变换的矩阵叫做裁剪矩阵(Clip Matrix),也被成为投影矩阵(Projection Matrix)。

裁剪空间的裁剪范围由视锥体(View Frustum)来决定,而视锥体又有两种类型,这涉及两种投影:一种是正交投影(Orthographic Projection),另一种是透视投影(Perspective Projection)。

在视锥体6块裁剪平面中,有两块裁剪平面比较特殊,分别是近剪裁平面(Near Clip Plane)远剪裁平面(Far Clip Plane)。它们决定了摄像机可以看到的深度范围。

投影矩阵将顶点转换到裁剪空间中,其目的有二:

    • 首先是为投影做准备。这是个迷惑点,虽然投影矩阵的名称包含了投影二字,但它并没有真正进行投影工作,而是再为投影做准备。真正的投影发生在后面的齐次除法(Homogeneous Division)过程中。而经过投影矩阵的变换后,顶点的w分量会具有特殊意义。
    • 其次是对x、y、z分量进行缩放。直接使用视锥体的6个才见平面来进行裁剪会比较麻烦。而经过投影矩阵缩放后,我们可以直接使用w分量座位一个范围值,如果x、y、z分量都位于这个范围内,就说明该顶点位于裁剪空间内。

透视投影

视锥体是由6个裁剪面所构成的,在Unity中,这6个裁剪平面则是由Camera组件中的参数和Game视图的横纵比共同决定。

由图看出,可以通过Camera组件的Field of View(简称FOV)属性来改变视锥体竖直方向的张开角度,而Clipping Planes中的Near和Far参数可以控制视锥体的近裁剪平面和远裁剪平面距离相机的远近。这样就可以求出视锥体近裁剪平面和远裁剪平面的高度,即:

现在还缺乏横向的信息。可以通过摄像机的横纵比得到。在Unity中,一个摄像机的横纵比由Game视图的横纵比和Viewport Rect中的W和H属性共同决定。假设前摄像机的横纵比为Aspect,则可以定义:

现在,我们可以根据已知的Near、Far、FOV和Aspect的值来确定透视投影的投影矩阵(P矩阵)。

一个顶点和上述P矩阵相乘后,可以有观察空间变换到裁剪空间中:

从结果看,这个投影矩阵本质就是对x、y和z分量进行不同程度的缩放(z分量还做了一个平移),缩放的目的是为了方便裁剪。注意,此时w分量不再是1,而是原先z分量的取反结果。现在就可以按如下不等式判断一个变换后的顶点是否位于视锥体内。如果一个顶点在视锥体内,那么他变换后的坐标必须满足:

任何不满足上述条件的图元都需要被剔除或者裁剪。

再见矩阵会改变空间转向性:空间从右手坐标系变换到了左手坐标系。这意味着离摄像机越远,z值越大。

正交投影

正交投影中的6个裁剪平面也是有Camera组件中的参数和Game视图的横纵比共同决定的。

正交投影的视锥体是一个长方形,因此计算上相比透视投影来说更加简单。由图可以看出,可以通过Camera组件的Size属性来改变视锥体竖直方向上高度的一般,而Clipping Planes中的Near和Far参数可以控制视锥体的金裁剪平面和远裁剪平面的远近。所以可以求出近远才见平面的高度:

设摄像机的横纵比为Aspect那么:

得到Near、Far、Size和Aspect的值,就可以确定正交投影的投影矩阵,如下:

同样,这里的投影矩阵是建立在Unity对坐标系的假定上面的。

一个顶点和上述投影矩阵相乘后的结果如下:

注意到,和透视投影不同的是,使用正交投影的投影矩阵对顶点进行变换后,w分量仍然为1。

本质:因为投影矩阵最后一行的不同,透视投影的投影矩阵的最后一行是【0 0 -1 0】,而正交投影矩阵的最后一行是【0 0 0 1】。这样做是为了在齐次除法上做准备。下一小节说明。

判断一个变换后的顶点是否为视锥体内使用的不等式和透视投影中的一样,这种通用性也是为什么要是用投影矩阵的原因之一。

屏幕空间

经过投影矩阵的变换后,就可以进行裁剪操作。当完成了所有裁剪工作后,就需要进行真正的投影了,也就是说,我们需要把视锥体投影到屏幕空间(Screen Space)。经过这一步变换,就会得到真正的像素位置,而不是虚拟的三维坐标。

屏幕空间是一个二维空间,因此,必须把顶点从裁剪空间投影到屏幕空间中,来生成对应的2D坐标。这个过程可以理解为两个步骤:

首先,需要进行标准齐次除法(Homogeneous Division),也被成为透视除法(Perspective Division)。实际上就是用齐次坐标系的w分量去除x、y、z分量。在OpenGL中,这一步得到的坐标叫做归一化设备坐标(Normalized Device Coordinates,NDC)。经过这一步可以把坐标从齐次裁剪坐标空间转换到NDC中。经过透视投影变幻后的裁剪空间,经过齐次除法后会变换到一个立方体内。在OpenGL的传统,这个立方体的x、y、z分量的范围都是【-1,1】。在DirectX中,z的分量范围是【0,1】。Unity则选了OpenGL这样的齐次裁剪空间。

对于正交投影来说,他的裁剪空间实际上已经是一个立方体了,w分量是1,所以齐次除法不会对顶点x、y、z产生影响。

经过齐次除法后,透视、正交投影的视锥体都变换到一个相同的立方体内。现在就可以根据变换后的x和y坐标来映射输出窗口的对应像素坐标(pixelWidth,pixelHeight)。

在Unity中,屏幕空间左下角的像素做标识(0,0),右上角像素坐标是(pixelWidth,pixelHeight)。由于当前x和y坐标都是【-1,1】,因此这个映射过程就是一个缩放过程。

齐次除法和屏幕映射的过程可以使用下面的公式来总结:

上面的式子对x和y分量都进行了处理,z分量一般会被用于深度缓冲。一个传统的方式是把

的值直接存进深度缓冲中,但这不是必须的。通常驱动生产商会根据硬件来选择最好的存储方式。此时clipw也并不会被抛弃,他回来后续一些工作中起到重要作用,例如进行透视校正差值。

验证过程可查看《UnityShader入门精要》4.6.8

世界空间的应用

不规则平面的Tilling:以世界坐标当做uv进行采样。

※P矩阵推导过程

--------------------------------------------------参考Games101 P4----------------------------------------------------

链接Lecture 04 Transformation Cont._哔哩哔哩_bilibili 时间轴:43:00

推导前定义的环境:

【camera】

  • camera再原点
  • 朝向-Z方向
  • Y轴为向上方向

正交投影

过程理解:

      • t、r、n、I、b、f是立方体的上下左右前后的范围。
      • 将包围盒经过平移->缩放(暂时不考虑旋转),映射到最右边一个标准的立方体上。
      • 由于是看向Z轴负方向,所以[f,n],远(f)的点数值小于近(n)的点
      • 右手坐标系来看

    1. 首先定义了立方体:y轴方向:t&b(上下);x轴方向:l&r(左右);z轴方向n&f(近远)此处n的数值>f(看向-Z方向,n离得近)
    2. 目的:
      • 把给定的定义好的立方体 映射到[-1,1]3标准立方体
      • 把左边的3个坐标轴分开考虑
      • x轴:(其他两个轴同理)
      • 写出x的范围表达式 → 重点:①映射到[-1,1]范围,②再写成线性表达式(ax+b)a就是缩放矩阵,b就是平移矩阵

过程理解:

      • 从右往左看,先看位移矩阵。
      • 如果是正常移出的话就是正的,将物体移回原点则前面加个负号。
      • (r+l)/ 2则是将对应轴移到原点上,其他轴坐标同理。
      • 2/(r-l),因为(r-l)是两点之间的距离,假如覆盖范围为1的话则可以得到(r-l)* x = 1,现在-1到+1区间是覆盖范围是2,所以的(r-l)* x = 2,所以得到x= 2/(r-l)

得到:Mortho=

 

透视投影

透视投影可以理解为将下图左边的平截头体通过“挤压”其右侧大的面,“挤压”成一个标准的立方体,例如图右的标准立方体。这样后续再求透视投影矩阵直接带入正交投影矩阵里就可以了。(因为正交投影矩阵相对来说计算简单)。

依旧是按右手坐标系来算

挤压后的特性:

    • 近平面上所有点不会变化
    • 远平面上所有点的z轴坐标不会发生变化
    • 远平面上的中心点任何坐标都不会变化

目的:

    • 先计算

      透视到正交的投影矩阵。
    • 再计算投影矩阵的到最终的投影矩阵。

假设从箭头方向看标记的两个点则横截面图如下:

由上图可知,根据相似三角形的特性,可以得到图右的公式。同理可以得到

想要一个挤压前的点转换到挤压后的点坐标,公式可以这样写:

因为Z前后关系不清楚,用unknown代替。

=>新概念引入

齐次坐标下的一个点(x,y,z,1)同时乘以一个常量k!=0,点不变,当k为z时具有同样的特性。

由此特性可以将矩阵中数全部乘以z得到

这样就可以知道:

所以可以知道此投影矩阵一部分数值:

此时回到开始定义的挤压后的特性:

近平面上所有点不会变化。

远平面上所有点的z轴坐标不会发生变化

则可以把矩阵中的z全部转换为n。所以挤压前的点=>挤压后的点

又根据齐次坐标系的性质,同时乘以一个数,点不变,则得到

所以由矩阵的第三行(0 0 A B)乘以得到的矩阵

(因为最后的到的n平方和x、y没有关系,因为是在近平面上计算的,所以前两个数值为0)

上面所计算的可以得到一下线性方程:

此时用到最后一个特性:远平面上的中心点任何坐标都不会变化。

要与上面点的映射一值所以这里需要同时乘以f。

计算所得两个线性方程:

带入可以得到透视到正交的投影矩阵:

Mpersp->ortho=

 

得到最终的透视矩阵则计算:

Mpersp=MorthoMpersp->ortho

又由于此为标准立方体,则可以得到t = -b,l = -r,且2t得到的是立方体高度h,2l得到的是立方体宽度w,h、w同时也是相机视口高宽,带入上式可化简为:

再次根据下图可以求得w、h、和FOV之间的关系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试题更新之-DOCTYPE html相关问题

文章目录 <!DOCTYPE html>是什么&#xff1f;为什么要在html文件开头加上一个<!DOCTYPE html>DOCTYPE的作用&#xff0c;严格与混杂模式的区别&#xff0c;有何意义HTML5为什么只需要写<!DOCTYPE HTML> 是什么&#xff1f; 是HTML文档的文档类型声明&#xf…

Redis进阶

Redis之父安特雷兹 redis x.x.x第二位是偶数的是稳定版本 redis7安装单机物理机安装&#xff1a; https://blog.csdn.net/G189D/article/details/129185947 数据类型 bitmap 统计二值状态的数据类型 最大位数2^32位&#xff0c;他可以极大的节约存储空间&#xff0c;使用…

postman 自动化测试

postman 自动化测试 0、写在前面1、变量引用1.1、如何在请求体中引用变量 0、写在前面 在有些时候看官方文档 比网上搜索效率要高&#xff0c; 比如网上搜一通还是不知道用法或者没有搜索到你想要的用法的时候。 postman官方文档 : https://learning.postman.com/docs/introdu…

layui选项卡演示

layui选项卡演示 .1 引入layui2. 选项卡演示实列3.js分离的代码4运行结果 在前端开发中&#xff0c;选项卡常用于展示多个内容模块&#xff0c;提供用户友好的界面交互方式。layui作为一款简洁易用的前端框架&#xff0c;提供了丰富的组件库&#xff0c;其中包括了强大且易用的…

《MySQL》事务

文章目录 概念事务的操作属性&#xff08;aicd&#xff09; 概念 一组DML语句&#xff0c;这组语句要一次性执行完毕&#xff0c;是一个整体 为什么要有事务&#xff1f; 为应用层提供便捷服务 事务的操作 有一stu表 # 查看事务提交方式(默认是开启的) show variables like au…

pytorch深度学习逻辑回归 logistic regression

# logistic regression 二分类 # 导入pytorch 和 torchvision import numpy as np import torch import torchvision from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import matplotlib.pyplot as …

Kafka第二课-代码实战、参数配置详解、设计原理详解

一、代码实战 一、普通java程序实战 引入依赖 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>2.4.1</version></dependency><dependency>&l…

Ceph的安装部署

文章目录 一、存储基础1.1 单机存储设备1.2 单机存储的问题1.3分布式存储&#xff08;软件定义的存储 SDS&#xff09; 二、Ceph 简介2.1 Ceph 优势2.2 Ceph 架构2.3 Ceph 核心组件2.4 Pool、PG 和 OSD 的关系&#xff1a;2.5 OSD 存储后端2.6 Ceph 数据的存储过程2.7 Ceph 版本…

面向初学者的卷积神经网络

卷积神经网络在机器学习中非常重要。如果你想做计算机视觉或图像识别任务&#xff0c;你根本离不开它们。但是很难理解它们是如何工作的。 在这篇文章中&#xff0c;我们将讨论卷积神经网络背后的机制、它的优点和应用领域。 什么是神经网络&#xff1f; 首先&#xff0c;让…

架构训练营:3-3设计备选方案与架构细化

3架构中期 什么是备选架构&#xff1f; 备选架构定义了系统可行的架构模式和技术选型 备选方案筛选过程 头脑风暴 &#xff1a;对可选技术进行排列组合&#xff0c;得到可能的方案 红线筛选&#xff1a;根据系统明确的约束和限定&#xff0c;一票否决某些方案&#xff08;主要…

Docker 安装 Nginx,并实现负载均衡

1、获取 nginx 的镜像 # 默认是latest版本docker pull nginx 2、运行 nginx 容器 docker run --name nginx-80 -p 80:80 --rm -d nginx# --name nginx-80 设定容器的名称# -p 80:80 端口进行映射&#xff0c;将本地的80端口映射到容器内部的80端口# --rm 表示容器退出后直接…

Vue中v-html用法以及指令汇总

操作数组的方法 &#xff1a; push&#xff1a;数组最后位置新增元素 pop&#xff1a; 删除最后一个元素 shift&#xff1a; 删除第一个元素 unshift&#xff1a;往前面加一个元素 splice&#xff1a;在数组的指定位置插入、删除、替换一个元素 sort&#xff1a; 数组排序…

卷积神经网络(CNN)原理详解

近些年人工智能发展迅速&#xff0c;在图像识别、语音识别、物体识别等各种场景上深度学习取得了巨大的成功&#xff0c;例如AlphaGo击败世界围棋冠军&#xff0c;iPhone X内置了人脸识别解锁功能等等&#xff0c;很多AI产品在世界上引起了很大的轰动。 而其中 卷积神经网络&am…

【微信小程序-uniapp】CustomButton 自定义常用吸底按钮组件

1. 效果图 2. 组件完整代码 <template><view:class="[custom-btn flex-center, size == big ? big : mid, type == primary ? primary : info, plain ? plain : , disabled ? disabled : , round ? round : ]"

神经网络之VGG

目录 1.VGG的简单介绍 1.2结构图 3.参考代码 VGGNet-16 架构&#xff1a;完整指南 |卡格尔 (kaggle.com) 1.VGG的简单介绍 经典卷积神经网络的基本组成部分是下面的这个序列&#xff1a; 带填充以保持分辨率的卷积层&#xff1b; 非线性激活函数&#xff0c;如ReLU&a…

挖矿记录+解决方案:利用GitLab组件对服务器进行挖矿导致CPU占用200%

文章目录 什么是云服务器挖矿?事件记录事件分析产生影响解决方案后期预防什么是云服务器挖矿? 云服务器挖矿是指利用云服务器从事赚取比特币的活动。比特币是一种虚拟数字货币,挖矿是将一段时间内比特币系统中发生的交易进行确认,并记录在区块链上形成新区块的过程。 用于…

Mybatis:传参+提交事务(自动or手动)+sql多表关联查询(两种方法)

目录 一、参数两种类型&#xff1a; 二、传参的几种方法&#xff1a; 三、提交事务 四、sql多表关联查询(两种方法) 一、参数两种类型&#xff1a; 1.#{参数}&#xff1a;预编译方式&#xff0c;更安全&#xff0c;只用于向sql中传值&#xff1b; select * from admin w…

只需一个提示词解除GPT-4的字符限制!

ChatGPT的内存有限,GPT-3.5-turbo的限制为4897个令牌,而GPT-4的最大限制为8192。如果您在使用GPT-4进行聊天时超过8192个令牌(约6827个单词),它就会开始遗忘。我想出了一种新的技巧,可以轻松将对话扩展10倍。 这种技巧不会将对话中的每个字都保存到内存中。当您去开会时,会有人…

如何解除“无法完成操作 因为文件包含病毒或潜在垃圾软件”

当运行软件遇到“无法完成操作 因为文件包含病毒或潜在垃圾软件”时&#xff0c;如何解决&#xff1f;如果确认此软件不是病毒软件&#xff0c;那么可以按照如下方法进行解决&#xff1a; 1&#xff1a;关闭防火墙 控制面板-系统和安全-Windows Defender防火墙-自定义设置&am…

分布式运用存储系统Ceph

一、ceph的相关知识 1.ceph介绍与简介 Ceph是一个开源的分布式存储解决方案&#xff0c;旨在提供可扩展性、高性能和强大的数据可靠性。它采用了一种分布式对象存储架构&#xff0c;能够同时提供块存储和文件存储的功能。 Ceph使用C语言开发&#xff0c;是一个开放、自我修复和…