第十三章 使用深度和法线纹理

获取深度和法线纹理

背后的原理

深度纹理是一张渲染纹理,它里面存储的像素值不是颜色,而是一个高精度的深度值。深度值范围是[0, 1],非线性分布的。这些深度值来自于顶点变换后得到的归一化的设备坐标(NDC)。一个模型想要被绘制在屏幕上,需要把它的顶点从模型空间变换到齐次裁剪坐标系下,这是通过顶点着色器中乘以MVP变换矩阵得到的。在变换的最后一步,我们需要用一个投影矩阵来变换顶点,当我们使用的是透视投影类型的摄像机时,这个投影矩阵就是非线性的。

透视投影对顶点的变换过程。左侧显示投影变换前,观察空间下视锥体的结构及相应顶点位置。中间显示应用裁剪矩阵之后的变换结果,顶点着色器阶段输出的顶点变换结果。右侧是底层硬件进行了透视除法后得到的归一化的设备坐标。

使用正交摄像机时投影变换过程。同样会得到一个范围为[-1, 1]的立方体,正交投影使用的变换矩阵是线性的。

得到NDC之后,深度值就对应了NDC中顶点坐标的z分量的值。由于NDC中z分量值范围-1~1,为了存储在一张图像中,我们需要对其映射。

d=0.5\cdot z_{ndc}+0.5

d对应了深度纹理中的像素值,z_{ndc}对应了z分量的值。

在Unity中,深度纹理可以直接来自于真正的深度缓存,也可以是由一个单独的Pass渲染而得。Unity会使用着色器替换技术选择那些渲染类型(RenderType)标签为Opaque的物体,判断它们使用的渲染队列是否小于等于2500,如果满足条件,就把它渲染到深度和法线纹理中。

如何获取

只需要告诉Unity并在Shader中直接访问特定纹理属性。与Unity沟通过程是在脚本设置摄像机的depthTextureMode完成的,我们可以通过如下代码获取深度纹理值

camera.depthTextureMode = DepthTextureMode.Depth;

设置好上面摄像机后,就可以在Shader中通过声明_CameraDepthTexture变量来访问它。

如果想要获取深度+法线纹理,只需要在代码中这样设置

camera.depthTextureMode = DepthTextureMode.DepthNormals;

在Shader中通过声明_CameraDepthNormalTexture变量来访问它。

在Unity中,我们还可以在摄像机的Camera组件上看到当前摄像机是否需要渲染深度或深度+法线纹理。当在Shader中访问到深度纹理_CameraDepthTexture后,我们就可以使用当前像素的纹理坐标对它采样,Unity为我们提供一个统一的宏SAMPLE_DEPTH_TEXTURE来处理这些平台差异造成的问题。

float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);

i.uv是一个float2类型的变量,对应了当前像素的纹理坐标。SAMPLE_DEPTH_TEXTURE接受两个参数-深度纹理和一个float3或float4类型的纹理坐标。类似的宏还有SAMPLE_DEPTH_TEXTURE_PROJ、SAMPLE_DEPTH_TEXTURE_LOD。SAMPLE_DEPTH_TEXTURE_PROJ的内部使用了tex2Dproj这样的函数进行投影纹理采样,纹理坐标的前两个分量首先会除以最后一个分量,再进行纹理采样。如果提供了第四个分量,还会进行一次比较,通常用于阴影的实现中。SAMPLE_DEPTH_TEXTURE_PROJ的第二个参数通常是由顶点着色器输出插值而得的屏幕坐标。

float d = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.scrPos));

其中,i.scrPos是在顶点着色器中通过调用ComputeScreenPos(o.pos)得到的屏幕坐标。

当通过纹理采样得到深度值后,这些深度值往往是非线性的,这种非线性来自透视投影使用的裁剪矩阵。但是,我们需要把投影后的深度值变换到线性空间下。我们只需要倒推顶点变换的过程即可。

Unity提供了两个辅助函数来为我们进行上述计算过程:LinearEyeDepth和Linear01Depth。LinearEyeDepth负责把深度纹理的采样结果转换到视角空间下的深度值,也就是z_{view}。Linear01Depth会返回一个范围在[0, 1]的线性深度值,也就是z_{01}。这两个函数使用了内置的_ZBufferParams变量来得到远近裁剪平面的距离。如果我们需要获取深度+法线纹理,可以直接使用tex2D函数对_CameraDepthNormalsTexture进行采样,得到里面存储的深度和法线信息。Unity提供了辅助函数来为我们对这个采样结果进行解码,从而得到深度值和法线方向。这个函数是DecodeDepthNormal,它的第一个参数是对深度+法线纹理的采样结果。这个采样结果是Unity对深度和法线信息编码后的结果,它的xy分量存储的是视角空间下的法线信息,而深度信息被编码进了zw分量。通过调用DecodeDepthNormal函数对采样结果解码后,我们就可以得到解码后的深度值和法线。这个深度值是范围在[0, 1]的线性深度值,而得到的法线则是视角空间下的法线方向。我们也可以用DecodeFloatRG和DecodeViewNormalStereo来解码深度+法线纹理中的深度和法线信息。

查看深度和法线纹理

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

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

相关文章

嵌入式工程师如何摸鱼?

有老铁问我,做嵌入式开发要加班吗? 也不知道搞什么鬼,现在的年轻人对加班这么抵触。 我刚做开发那会,啥也不懂,每天基本都要加班到晚上7-9点不等,我并不抵触加班,因为早早回家,也没什…

时间同步服务项目练习

一.配置server主机要求如下: 1.server主机的主机名称为 ntp_server.example.com 2.server主机的IP为: 172.25.254.100 3.server主机的时间为1984-11-11 11:11:11 4.配置server主机的时间同步服务要求可以被所有人使用 二.设定cli…

【保姆级】2024年OnlyFans订阅指南

OnlyFans是一个独特的社交媒体平台,它为创作者和粉丝提供了一个互动交流的空间。通过这个平台,创作者可以分享他们的独家内容,而粉丝则可以通过订阅来支持和享受这些内容。如果你对OnlyFans感兴趣,并希望成为其中的一员&#xff0…

Delphi Xe 10.3 钉钉SDK开发——审批流接口(获取表单ProcessCode)

开发钉钉审批流时,需要用到钉钉表单的Processcode,有两种方法 : 一、手动获取: 管理员后台——审批——找到对应的表单:如图: ProcessCode后面就是了! 二、接口获取:今天的重点&a…

机器学习周报第37周

目录 一、文献阅读:You Only Look Once: Unified, Real-Time Object Detection1.1 摘要1.2 背景1.3 论文模型1.4 网络设计1.5 YOLO的局限性1.6 实现代码 一、文献阅读:You Only Look Once: Unified, Real-Time Object Detection 1.1 摘要 YOLO是一种新…

JDBC入门

JDBC java database connectivity: 就是使用java语言操作关系型数据库的一套API

Pytest测试用例中的mark用法(包含代码示例与使用场景详解)

在软件开发中,测试是确保代码质量和功能稳定性的重要环节。Python作为一门流行的编程语言,拥有丰富的测试工具和框架,其中pytest是其中之一。pytest提供了丰富的功能来简化测试用例的编写,其中的mark功能允许我们对测试用例进行标…

LeetCode———100——相同的树

目录 ​编辑 1.题目 2.解答 1.题目 . - 力扣(LeetCode) 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1&…

【数据挖掘】实验8:分类与预测建模

实验8:分类与预测建模 一:实验目的与要求 1:学习和掌握回归分析、决策树、人工神经网络、KNN算法、朴素贝叶斯分类等机器学习算法在R语言中的应用。 2:了解其他分类与预测算法函数。 3:学习和掌握分类与预测算法的评…

《QT实用小工具·二十七》各种炫酷的样式表

1、概述 源码放在文章末尾 该项目实现了各种炫酷的样式表,如单选、多选、按钮、日历、表格、下拉框、滚轮等,下面是项目demo演示: 项目部分代码如下: #include "frmmain.h" #include "ui_frmmain.h" #inc…

从入门到精通C++之类和对象(续)

目录 初始化列表构造函数?拷贝构造?浅谈explicit关键字友元 内部类static成员总结 初始化列表 引入初始化列表:简化代码,提高效率 在编程中,初始化列表是一种用于在创建对象时初始化成员变量的快捷方式。通过初始化列…

数据结构(七)——B树和B+树

7.4.1_1 B树 5叉查找树 //5叉排序树的结点定义 struct Node {ElemType keys[4]; //最多4个关键字struct Node &child[5]; //最多5个孩子int num; //结点中有几个关键字 }; 如何保证查找效率? eg:对于5叉排序树,规定…

校园智能水电预付费管理系统

校园智能水电预付费管理系统是一种专为学校水电资源管理而设计的智能化系统,旨在提供全面的水电资源管理解决方案,满足校园管理者对水电资源管理的需求。该系统整合了先进的智能技术和云计算,为校园管理者提供了实时监控、自动计费、节能管理…

钉钉OA审批评论接口,如何@ 人并发送通知

钉钉OA审批评论接口,如何 人并发送通 问题描述: 相关接口:https://oapi.dingtalk.com/topapi/process/instance/comment/add 我希望在钉钉oa审批流程中,添加评论的同时通过“”或者其他方式提醒流程发起人去跟进审批工作。 但我…

【Linux】Linux信号

目录 信号的概念 生活中的信号 Linux中的信号 kill命令 kill 命令的使用 常见的信号 命令行代码示例 注意事项 信号的处理方式 产生信号 信号的捕捉 信号捕捉示意图 内核如何实现信号捕捉 信号的捕捉与处理 小结 阻塞信号 信号在内核中的表示图 信号集操作函数…

linux 挂载云盘 NT只能挂载2T,使用parted挂载超过2T云盘

一、删除原来挂载好的云盘和分区 1、查看挂载号的云盘 fdisk -l 发现我们有5千多G但是只挂载了2T,心里非常的慌张!十分的不爽! 好,我们把它干掉,重新分区! 2、解除挂载 umount /homeE 没保存跳转到&…

「每日跟读」英语常用句型公式 第14篇

「每日跟读」英语常用句型公式 第14篇 1. As far as __ is concerned 就__ 而言 As far as the project timeline is concerned, we’re running ahead of schedule. (就项目时间表而言,我们进度超前了。) As far as the exam results ar…

二分查找的时间复杂度的讲解

二分查找的代码: 二分查找的时间复杂度: 最坏的情况: 就是找不到和查找区间只剩一个值的时候,这两种都是最坏的结果,假设查找了x次,达到了最坏的结果: N代表每一次折半区间数据的个数&#xf…

GNeRF的一些具体细节

Abstract GNeRF,一个结合生成对抗网络(GAN)和神经辐射场(NeRF)重建的框架,用于未知甚至随机初始化相机姿态的复杂场景。最近基于 NERF 的进展已经获得了显着的现实新视图合成的普及。然而,大多数方法都严重依赖于摄像机姿态的精确估计&#…

【过程11】——教育被点燃的路上

这里写目录标题 一、背景二、过程1.两年四十万的认知改变2.三年打工仔的经历改变3.一年计算机的人生蜕变4.后面的展望 三、总结 一、背景 人生在世,对于一些事情的笃信笃行;背后真的会有莫大无以言表的波涛。 这个事情到现在已经五年半左右时间了&#…