剪切空间与归一化设备坐标【NDC】

有了投影变换的知识,我们现在可以讨论剪切空间(Clip Space)和 归一化设备坐标(NDC:Normalized Device Coordinates)。 为了理解这些主题,我们还需要深入了解齐次坐标的有趣世界。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎

1、透视相机回顾

请记住,透视相机被建模为称为视锥体(view frustum)的截棱锥体。

该视锥体由需要定义的几个部分组成,以便创建我们的投影矩阵:

  • 近平面 - 这是通过负 z 轴(在相机空间中定义)到近剪裁平面的距离
  • 远平面 - 这是通过负 z 轴(在相机空间中定义)到远剪裁平面的距离
  • 视场 (fov_y) - 这是平截头体顶边和底边之间的角度。
  • 纵横比 - 这是我们窗口的纵横比。

近平面和远平面之间的距离应尽可能短,以最大限度地减少深度缓冲区精度问题或避免深度冲突(z-fighting)。

让我们假设我们的场景使用透视相机来进行此计算。 请记住,透视相机建模和正交相机建模之间存在差异。

有了 gl-matrix,我们的工作就非常简单了。 我们只需要将一些参数传递给该方法,如下所示:

 	const aspect = this._context.canvas.width / this._context.canvas.height;const projectionMatrix = mat4.create();const fov_y = (2 * Math.PI) / 5const near = 1const far = 100mat4.perspective(projectionMatrix, fov_y, aspect, near, far);

如果你有机会需要自己构建数组,那也不会太糟糕:

请注意,矩阵位置 [3][2] 处有一个 -1(假设矩阵索引为 0),因为视图空间中的 z 分量(负数)在乘以投影矩阵后成为我们的分量 w:

注意:请参阅 此图并注意相机空间和剪切空间中 z 轴方向的差异,从右手坐标系变成左手坐标系。

让我们把这个透视模型放在后袋里,继续通过在渲染管道中发挥重要作用的两个空间—剪切空间和 NDC(标准化坐标)进行顶点变换的故事。

但在我们去那里之前,我们还有一站……齐次坐标。

2、齐次坐标

啊,一周前齐次坐标吓到了我。 我很快意识到它们一点也不可怕。 实际上,它们在我们的 3D 工具箱中非常有用。

因此,为了开始我们的讨论,让我们以两周前位于三角形中的顶点为例:

为什么有四个维度? 该顶点的位置被认为是齐次坐标,因为有第四个分量 w。 我们从一开始就与他们打交道!

我们需要第四个维度有几个原因。 在下一部分中,我们将了解如何使用它们,以及 GPU 如何使用它们(从剪切空间更改为 NDC)。

齐次坐标有几个应用程序将立即对我们有用。 请注意,此列表并不完整。 齐次坐标的应用非常广泛!

2.1 投影变换

我们使用齐次坐标在射影空间中工作。

让我们看一个 2D 示例来简化这个概念:

从图中我们可以看出,w 与投影有关。 想象一下,我们将电影放映机靠近屏幕。

图像应该缩小! 此外,如果我们将电影放映机移离屏幕,图像应该会变大! 因此可以推断,w 分量影响图像相对于投影的比例。

稍后我们将看到 GPU 如何使用该值来渲染具有正确透视错觉的图像。

w 总是 = 1 吗?

我想首先要问的问题是:w = 1,这是什么意思?

正如我们刚刚看到的,w 值描述了组件相对于投影距离的比例。 因此,值为 1 意味着不会发生缩放。 因此,当 w = 1 时,它对 x、y 或 z 分量的值没有影响。

所以设置w=1是一个非常合理的初始值。 在代码中,当我们定义顶点时,我们将值设置为 1,这实际上将该组件的更新责任委托给了投影矩阵。

因此,一旦完成所有计算,w 可能不再等于 1。

2.2 3D坐标的平移

该应用程序在图形领域广泛使用。 事实上,一周前我们已经通过 4D LookAt 和 viewMatrix 矩阵看到了这一点。

通常平移向量被写为 3D 向量,并被认为是仿射变换。 此外,旋转和缩放矩阵也是 3D (3x3):

是否可以在单个矩阵中表示整个变换(平移、旋转、缩放)? 是的! 通过添加第四个分量 w,我们利用了第四维的力量:

一旦我们添加了第四个维度,我们就可以将这些矩阵相乘以构建单个矩阵,就像上周我们介绍 viewMatrix 时一样:

3、剪切空间

剪切空间(clip space) - 它是什么? 我认为这个例子可以帮助我们更清楚地看到事情:

简而言之,剪切空间被建模为棱柱,称为剪切体块(clip volume)。 如果图元的顶点在此空间之外,它们将被我们的 GPU 拒绝(剪裁)。 这样做是为了避免不必要的计算,因为无论如何我们都看不到这些顶点。

剪切体块的尺寸定义为以下边界框: (-w,-w,0), (w,w,w) ,其中w是顶点的额外维度,这使得顶点成为齐次坐标!

为了避免被 GPU 拒绝,剪切空间中的 x、y 和 z 分量必须满足以下条件:

如何进入剪切空间

我们的顶点被我们定位在剪切空间中。

为何如此? 将模型空间中的顶点转换为剪切空间所涉及的计算发生在顶点着色器中。 事实上,我们设置为输出的位置是剪切空间中的位置。

顶点着色器中通常使用的方程是:

out.position = projectionMatrix * viewMatrix * modelMatrix * inputModelSpacePosition

其中:

  • inputPosition - 模型空间中的 4D 顶点位置(齐次坐标)。
  • modelMatrix - 将输入顶点从模型空间转换到世界空间的 4x4 矩阵。
  • viewMatrix - 4x4 视图矩阵,它将世界空间中的一个点作为输入,结果是相机空间中的一个点。
  • projectionMatrix - 4x4 投影矩阵,它将相机空间中的一个点作为输入,结果是剪切空间中的投影点。

让我有点困惑的是每个顶点可以有不同的 wc 值。 因此,我们应该将剪切空间视为一个矩形棱柱,每个顶点都有其存在的自己的剪切空间。

如果三角形的顶点在同时落在剪切体块内部和外部会怎么样呢?

我们的 GPU 非常智能。 使用一种算法(我不会在本文中深入讨论),剪切空间之外的顶点将被裁剪,GPU 将在其位置重新绘制其他顶点,如上图所示。

结果是一个剪切基元,但仍然存在于场景中。 如果 GPU 认为有必要,这些新顶点可以创建额外的三角形。

4、NDC

裁剪剪切体块之外的顶点后,剩余顶点的位置将标准化为称为 NDC(标准化设备坐标)的通用坐标系。

GPU 通过执行称为透视除法的操作来完成进入该坐标系的工作,其中所有顶点分量除以 w 分量:

回想一下,我们刚刚剪掉了 w 维棱镜之外的所有顶点。 因此,通过将 x 和 y 分量除以 w 分量进行归一化后,我们的分量应介于 -1 和 1 之间。 对于 z 分量,标准化坐标将介于 0 和 1 之间。

⚠️ 每个图形 API 都不同,你应该查阅正在使用的图形 API 的文档,但对于 WebGPU,NDC 介于  (-1, -1, 0) 和  (1, 1, 1) 之间。

原文链接:Clip Space和NDC - BimAnt

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

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

相关文章

【PTA-C语言】实验三-循环结构I

如果代码存在问题,麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 实验三-循环结构I 7-1 求交错序列前N项和 (分数 15)7-2 寻找250(分数 15)7-3 最大公约数和最小公倍数(分数 15)7-4 统计字符&#xff0…

二十五、DSL查询文档(全文检索查询、精确查询、地理查询、复合查询)

目录 一、全文检索查询 1、match查询 语法: 2、multi_match查询 语法: 3、match和mult_match的区别 二、精确查询 1、term查询: 语法: 2、range查询:(范围查询) 语法: 三、地理查询 1、geo_bou…

Springboot如何快速生成分页展示以及统计条数

这是表结构: 前置知识: 分页查询公式(): -- 推导一个公式 -- select * from emp -- order by empno -- limit 每页显示记录数 * (第几页-1),每页显示记录数 统计条数公式: select count…

【动态规划】LeetCode-931.下降路径最小和

🎈算法那些事专栏说明:这是一个记录刷题日常的专栏,每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目,在这立下Flag🚩 🏠个人主页:Jammingpro 📕专栏链接&…

Wordpress自动定时发布怎么开通-Wordpress怎么自动发布原创文章

在当今数字化时代,博客已经成为许多人分享观点、经验和知识的重要平台。然而,对于博主们来说,每天按时发布一篇又一篇的文章可能是一项具有挑战性的任务。为了解决这个问题,一些创新的工具应运而生,其中包括WordPress的…

Collection的其他相关知识

前置知识:可变参数 就是一种特殊参数,定义在方法 构造器的形参列表里,格式是:数据类型...参数名称; 可变参数的特点和好处 特点:可以不传数据给它;可以传一个或者同时传多个数据给它&#xff…

爬虫学习(三)用beautiful 解析html

安装库 import requests from bs4 import BeautifulSoup headers {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0"} for start_num in range(0,250…

【工作生活】汽车ECU开发内容简介

目录 1. 目标 2. 要分享什么 3.1 行业知识 3.1.1车载行业知识: 3.1.2项目: 3.1.3开发测试工具: 3.2 硬件平台 3.3 基础知识 3.4 工作生活 3. 我们是谁 1. 目标 随着新能源汽车的快速崛起,汽车电子行业开始快速发展&…

设计模式-结构型模式之外观设计模式

文章目录 七、外观模式 七、外观模式 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。它向现有的系统添加一个接口,来隐藏系统的复杂性。 这种模式涉及到一个单一的类,该类…

【华为OD题库-043】二维伞的雨滴效应-java

题目 普通的伞在二维平面世界中,左右两侧均有一条边,而两侧伞边最下面各有一个伞坠子,雨滴落到伞面,逐步流到伞坠处,会将伞坠的信息携带并落到地面,随着日积月累,地面会呈现伞坠的信息。 1、为了…

关于微信小程序中如何实现数据可视化-echarts动态渲染

移动端设备中,难免会涉及到数据的可视化展示、数据统计等等,本篇主要讲解原生微信小程序中嵌入echarts并进行动态渲染,实现数据可视化功能。 基础使用 首先在GitHub上下载echarts包 地址:https://github.com/ecomfe/echarts-for…

【JavaEE初阶】Thread 类及常见方法、线程的状态

目录 1、Thread 类及常见方法 1.1 Thread 的常见构造方法 1.2 Thread 的几个常见属性 1.3 启动⼀个线程 - start() 1.4 中断⼀个线程 1.5 等待⼀个线程 - join() 1.6 获取当前线程引用 1.7 休眠当前线程 2、线程的状态 2.1 观察线程的所有状态 2.2 线程状态和状…

大数据Hadoop-HDFS_架构、读写流程

大数据Hadoop-HDFS 基本系统架构 HDFS架构包含三个部分:NameNode,DataNode,Client。 NameNode:NameNode用于存储、生成文件系统的元数据。运行一个实例。 DataNode:DataNode用于存储实际的数据,将自己管理…

Buzz库python代码示例

Buzz库来编写一个下载器程序。 php <?php require_once vendor/autoload.php; // 引入Buzz库 use Buzz\Browser; use Buzz\Message\Response; $browser new Browser(); // 设置 $browser->setHttpClient(new HttpClientProxy([ host > , port > , ])…

单片机学习1——点亮一个LED灯

Keil软件编写程序&#xff1a; 特殊功能寄存器声明&#xff1a; #include<reg52.h>sbit LED P1^0;void main() {LED 0;while(1); } 代码说明&#xff1a; sbit 语句是特殊功能位声明。 生成HEX文件&#xff0c;这个文件是下载到单片机里的文件。Options for Target…

大数据Doris(三十二):Doris高级功能

文章目录 Doris高级功能 一、​​​​​​​表结构变更

hql面试题之字符串使用split分割,并选择其中的一部分字段的问题

版本&#xff1a;20231109 1.题目&#xff1a; 有两张表,a表有id和abstringr两个字段&#xff0c;b表也有id和bstr两个字段&#xff0c;具体如下 A表&#xff1a; 1abc,bcd,cdf2123,456,789 B表: 1acddef2123456 在a表的abstring字段中用‘,’分割&#xff0c;并取出前两…

数据结构实验任务六 :基于 Dijsktra 算法的最短路径求解

本次代码为实验六:基于 Dijsktra 算法的最短路径求解实现。本实验的重点在于对于Dijsktra算法的理解。有关Dijsktra的资料可以参考有关博文&#xff1a; 图论&#xff1a;Dijkstra算法——最详细的分析&#xff0c;图文并茂&#xff0c;一次看懂&#xff01;-CSDN博客 以下附上…

【数据结构实验】排序(一)冒泡排序改进算法 Bubble及其性能分析

文章目录 1. 引言2. 冒泡排序算法原理2.1 传统冒泡排序2.2 改进的冒泡排序 3. 实验内容3.1 实验题目&#xff08;一&#xff09;输入要求&#xff08;二&#xff09;输出要求 3.2 算法实现 4. 实验结果5. 实验结论 1. 引言 排序算法是计算机科学中一个重要而基础的研究领域&…

chatgpt prompt提示词

chatgpt的接口是一个标准的http请求&#xff0c;请求的url为 POST https://api.openai.com/v1/chat/completions 官方的接口文档地址为&#xff1a;https://platform.openai.com/docs/api-reference/chat/create Example request curl https://api.openai.com/v1/chat/comp…