当前位置: 首页 > news >正文

深度和法线纹理

屏幕后期处理效果的基本原理就是当游戏画面渲染完毕后通过获取到该画面的信息进行额外的效果处理 之前的边缘检测、高斯模糊、Bloom、运动模糊等效果都是基于获取当前屏幕图像中的像素信息进行后期处理

如果仅仅根据像素信息来进行一些效果处理,存在以下问题:

  1. 效果欠佳:比如实现边缘检测时,边缘检测信息受物体纹理和光照等因素影响,无法更准确的检测边缘,会得到一些我们不需要的边缘点
  2.  无法实现:比如我们想要实现一些景深效果(虚化背景),我们无法通过像素的颜色信息来判断离摄像机的远近

因此可以通过屏幕空间的深度纹理和法线纹理进行优化。

  • 屏幕空间深度纹理:用于存储屏幕图像中每个像素深度信息的纹理,制作出 边缘检测、运动模糊、景深、环境遮挡 等等效果
  • 屏幕空间法线纹理:用于存储屏幕图像中每个像素法线信息的纹理,制作出 边缘检测、运动模糊、景深、环境遮挡 等等效果

1、深度和法线纹理的使用

在Shader当中直接声明对应变量

  • 深度纹理:sampler2D _CameraDepthTexture;
  • 深度+法线纹理:sampler2D _CameraDepthNormalsTexture;(一般RG通道存储法线,BA通道存深度)之后直接在Shader中使用这两个变量便可以获取到相关信息

Shader中获取深度值:

Shader中获取法线信息:

2、深度纹理中存储的是什么信息

Unity中的深度纹理中存储的信息,也就是Shader中使用 _CameraDepthTexture 或_CameraDepthNormalsTexture 采样的信息,是进行裁剪空间变换后的 z 分量再转换到0~1之后的结果,因为齐次裁剪空间坐标范围为 -1 ~ 1,而纹理中存储的信息范围是 0 ~ 1,因此Unity会将其利用以下公式进行转换:深度纹理值 = 0.5 * z + 0.5

也就是说我们通过深度纹理直接采样得到的深度纹理值是是进行裁剪空间变换后的 z 分量再转换到0~1之后的结果

3、法线纹理中存储的是什么信息

Unity中的法线纹理中存储的信息,也就是Shader中使用_CameraDepthNormalsTexture采样得到的float4中的部分信息,它是观察空间下的 法线 再转换到0~1之后的结果,因为观察空间下的单位向量的分量取值范围是 -1~1,而纹理中存储的信息范围是 0 ~ 1,因此Unity会将其利用以下公式进行转换:法线纹理值 =(观察空间下法线 + 1)* 0.5【公式跟深度纹理值纠正是一样的,只不过要对x,y,z 都改变】

也就是说我们通过法线纹理直接采样得到的法线纹理值是是观察空间下的 法线 再转换到0~1之后的结果

4、Unity 如何得到深度和法线纹理的

Unity中深度和法线纹理一般通过两种途径获取

  • 从G-buffer几何缓冲区中获取
  • 由一个专门的Pass渲染而来

具体Unity是通过哪种方式获取,取决于使用的渲染路径和设备的硬件限制。
当使用延迟渲染路径时,深度和法线纹理可以直接访问到,因为延迟渲染路径会把信息存储到
G-buffer几何缓冲区中(深度和法线等信息都存储在其中)。
而当无法直接获取到深度和法线纹理时(比如硬件不支持延迟渲染路径 或 使用的是前向渲染路
径时),Unity会通过一个单独的Pass来进行渲染,获取深度和法线信息。

需要注意的是,当使用单独的Pass渲染获得深度和法线纹理时,两者是有区别的

  • 对于深度纹理来说:

Unity内部会使用着色器替换技术选择渲染类型 RenderType =“Opaque” (不透明物体)
然后判断它们的渲染队列Queue是否小于等于2500(Background-1000、Geometry-2000、AlphaTest-2450)
如果满足这个条件,就会使用物体投射阴影时的Pass(LightMode 为 ShadowCaster 的Pass)
来得到深度纹理,如果没有这个Pass,那么该物体不会出现在深度纹理中!
因此这里的重点是,如果我们希望物体能够正确的出现在深度纹理中

  1. 必须在Shader中正确的设置RenderType标签
  2. 必须有投射阴影用的Pass(LightMode为ShadowCaster的Pass)
  • 对于法线纹理来说:

Unity底层会使用一个单独的Pass把整个场景再次渲染一次,从而得到深度和法线信息
这里为什么是深度和法线信息呢,因为当需要得到法线纹理时,Unity中是和深度一起获取的
( _CameraDepthNormalsTexture )
这个Pass包含在Unity内置的Shader中,我们可以在官方下载源文件解压后进行查看

5、深度和法线纹理使用时调用的函数原理

  • 深度

  • 法线 

SAMPLE_DEPTH_TEXTURE 宏:
它是用于从深度纹理中进行采样的宏,相比直接用tex2D进行采样,它在内部会帮助我们适配各
种不同的平台
,因为不同平台对深度纹理的采样规则会有所不同。它采样得到的深度值是裁剪空间下的z分量转换到0~1之间的结果

通过SAMPLE_DEPTH_TEXTURE得到的深度值是非线性的,所谓的非线性值的是指在透视摄像机的裁剪空间中深度值分部不均匀

  • 当深度值接近裁剪面近时,深度值变化迅速,精度高
  • 当深度值接远裁剪面近时,深度值变化缓慢,精度低

更直观的解释:一个相机在观察一个3D场景时,近处的物体移动一点,视觉上变化很大,所以需
要更高的精度来记录这种变化。而远处的物体移动同样的距离,视觉上的变化很小,因此可以使
用较低的精度来记录

因此为了让我们在Shader中利用深度值进行的计算更加准确,我们需要获得线性的深度值,只需要把裁剪空间下的深度值转换到观察空间下,便可以得到线性的深度值
Unity Shader中提供了内置函数LinearEyeDepth 和 Linear01Depth 都可以得到观察空间下的线性深度值

  • LinearEyeDepth:得到的是像素到摄像机的实际距离
  • Linear01Depth:得到的是实际距离被压缩到0~1之间的值

DecodeDepthNormal函数内部其实也是执行的DecodeFloatRG和DecodeViewNormalStereo函数,它的作用就是得到观察空间下的对应像素的 法线 和 线性 深度值(0~1)
可以一次性的获得两个信息,也可以选择分别调用DecodeFloatRG和DecodeViewNormalStereo
单独获取深度和法线信息

函数中具体做的事情,就是利用法线的xy算出z,得到最终的法线信息;将裁剪空间下的非线性深度值 转换为观察空间下线性的范围为0~1的深度值

总结:直接采样出来的深度和法线信息是不会直接使用的,我们需要将他们通过内置函数进行转换
得到最终我们会使用的观察空间下的深度和法线信息

6、获取深度纹理

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DepthTexture : PostEffectBase
{// Start is called before the first frame updatevoid Start(){Camera.main.depthTextureMode = DepthTextureMode.Depth;   }
}
Shader "ShaderProj/13/DepthTexture"
{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;sampler2D _CameraDepthTexture;v2f vert (appdata_base v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);fixed linearDepth = Linear01Depth(depth);return fixed4(linearDepth, linearDepth, linearDepth, 1);}ENDCG}}Fallback Off
}

7、获取法线纹理

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DepthNormalsTexture : PostEffectBase
{// Start is called before the first frame updatevoid Start() {Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;}
}
Shader "ShaderProj/13/DepthNormalTexture"
{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;sampler2D _CameraDepthNormalsTexture;v2f vert (appdata_base v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{float4 depthNormal = tex2D(_CameraDepthNormalsTexture, i.uv);fixed depth;fixed3 normals;DecodeDepthNormal(depthNormal, depth, normals);return fixed4(normals * 0.5 + 0.5, 1);}ENDCG}}Fallback Off
}

 因为是按照观察空间来计算的,所以法线展示出来的颜色按照摄像机的【Local】坐标(x轴:右边,红色;y轴:上边,绿色;z 轴:朝向反向向,蓝色)

相关文章:

深度和法线纹理

屏幕后期处理效果的基本原理就是当游戏画面渲染完毕后通过获取到该画面的信息进行额外的效果处理 之前的边缘检测、高斯模糊、Bloom、运动模糊等效果都是基于获取当前屏幕图像中的像素信息进行后期处理的 如果仅仅根据像素信息来进行一些效果处理,存在以下问题&…...

监听H5页面在微信浏览器异常退出

参考文章 onBeforeUnmount(() > {unNormalExit(); });//---------------------------异常退出---------------------- function unNormalExit() {enterOrExitRoom({type: 37,roomId: roomId.value,userId: userId.value,nickName: name.value,loginUserType: 2, //0 专家 1…...

Linux 串口编程

目录 前言一、tty体系二、串口硬件基础知识三、Linux下的串口编程3.1 打开串口3.2 从串口读写数据,问题1、2的诞生3.3 关闭串口3.4 串口配置3.4.1 获取/设置串口的参数3.4.2 设置波特率3.4.3 设置控制模式标志3.4.4 设置本地模式标志3.4.5 设置输入模式标志3.4.6 设置输出模式标…...

Adminer源码编译 精简语言中英文和基本使用方法

Adminer是一个小而强悍的基于web的数据库管理工具, 官方默认支持几十种语言,但是对于中国的用户而言只需要有中文和英文就够了,其他语言基本无用。这就需要我们下载Adminer源码自己编译 Adminer.php , 如下图所示 adminer 中英文语言精简版本…...

go 中线程安全map

在 Go 语言中,官方包 sync.Map 确实提供了线程安全的映射数据结构。然而,正如你所提到的,使用 sync.Map 时,有时需要进行类型断言,这可能会让代码显得冗长或不直观。 如果你希望使用一个更加易用的线程安全映射&#…...

eslint 安装与使用-基础教程

中文官网 官方规则解析 规则参考 - ESLint - 插件化的 JavaScript 代码检查工具 eslint ESlint 是一个检查 JS,TS 语法的工具.能够与常用开发工具,例如 VS Code,进行集成并提供错误提示,和可能的修正方法 安装 安装eslint npm init esli…...

自然语言处理的未来愿景

自然语言处理的未来愿景 在这个信息爆炸的时代,计算机如何理解和生成我们日常使用的语言,已经成为一个引人注目的问题。你有没有想过,为什么智能助手能理解你的指令?又或者,为什么社交媒体上的推荐引擎能够精准地推荐你喜爱的内容?这背后,正是自然语言处理(NLP)在发挥…...

等保2.0三级测评华为华三交换机路由器

在使用本博客提供的学习笔记及相关内容时,请注意以下免责声明: 信息准确性:本博客的内容是基于作者的个人理解和经验,尽力确保信息的准确性和时效性,但不保证所有信息都完全正确或最新。 非专业建议:博客中的内容仅供参考,不能替代专业人士的意见和建议。在做出任何重要…...

BA和CS算法中的Levy飞行策略

Levy飞行策略通过模拟自然界中动物的长距离迁徙行为,指导粒子进行更大范围的搜索,有助于算法快速找到全局最优解。它是一种具有独特优势的随机行为策略,模拟随机游走或搜索过程中的步长和方向,其步长的概率分布为重尾分布&#xf…...

PHP:实现两张无关联表数据的联合分页处理方案

前言 在现代软件开发中,高效地处理数据是至关重要的环节。尤其是在使用 PHP 进行开发时,常常会遇到各种复杂的数据处理需求。其中,实现两张无关联表数据的联合分页处理就是一个具有挑战性的任务。这种需求在很多实际应用场景中都可能出现&am…...

【单元测试】单元测试介绍

1 单元测试基础 1.单元测试:单元测试又称模块测试,属于白盒测试,是最小单位的测试。模块分为程序模块和功能模块。功能模块指实现了一个完整功能的模块(单元),一个完整的程序单元具备输入、加工和输出三个…...

PyQt事件机制及其应用

一、实例前置 一个小闹钟应用 创建主窗口类 首先我们创建了一个名为AlarmClock的类,它继承自QMainWindow。这个类将包含我们的GUI组件和逻辑。 from Alarm_clock import Ui_MainWindowclass AlarmClock(QMainWindow):def __init__(self):super().__init__()# 初始化…...

厦门凯酷全科技有限公司抖音电商服务的卓越典范

在短视频和直播带货迅速崛起的时代,厦门凯酷全科技有限公司(以下简称“凯酷全科技”)以其专业的服务、创新的精神以及对市场的深刻理解,在抖音电商领域中脱颖而出,成为众多品牌商家信赖的选择。本文将深入探讨凯酷全科…...

vue3水波柱状图 ,实现

效果图 //引用页面 <div style"height: 60px;background-color: #fff;border-radius: 5px;width: 40px;"><WavePercentage:percentage"progress"primary-color"#ffcb7c"secondary-color"#ffcb7c"/></div>import Wa…...

如何在两台 PostgreSQL 服务器之间使用逻辑复制槽进行数据复制

如何在两台 PostgreSQL 服务器之间使用逻辑复制槽进行数据复制 如何在两台 PostgreSQL 服务器之间使用逻辑复制槽进行数据复制环境准备1. 配置主服务器&#xff08;Publisher&#xff09;1.1 修改 postgresql.conf1.2 修改 pg_hba.conf1.3 重启 PostgreSQL 服务1.4 创建逻辑复制…...

System.Data.OracleClient 需要 Oracle 客户端软件 version 8.1.7 或更高版本

问题1&#xff1a;“/”应用程序中的服务器错误。 System.Data.OracleClient 需要 Oracle 客户端软件 version 8.1.7 或更高版本。 说明: 执行当前 Web 请求期间&#xff0c;出现未经处理的异常。请检查堆栈跟踪信息&#xff0c;以了解有关该错误以及代码中导致错误的出处的详细…...

【机器人】振动分析和控制工具之Bode图

Bode 图完整介绍 Bode 图由两个部分组成&#xff1a; 幅值图 (Magnitude Plot)&#xff1a;描述系统对不同频率输入信号的增益大小&#xff08;幅值响应&#xff09;。相位图 (Phase Plot)&#xff1a;描述系统输出信号相对于输入信号的相位差。 Bode 图的横轴是频率&#x…...

生成:安卓证书uniapp

地址&#xff1a; https://ask.dcloud.net.cn/article/35777 // 使用keytool -genkey命令生成证书&#xff1a; 官网&#xff1a; keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore ----------------------------------…...

酒店/电影推荐系统里面如何应用深度学习如CNN?

【1】酒店推荐系统里面如何应用CNN&#xff1f;具体过程是什么 在酒店推荐系统中应用卷积神经网络&#xff08;CNN&#xff09;并不是一个常见的选择&#xff0c;因为 CNN 主要用于处理具有空间结构的数据&#xff0c;如图像、音频和某些类型的序列数据。然而&#xff0c;在某…...

【CSS in Depth 2 精译_069】11.3 利用 OKLCH 颜色值来处理 CSS 中的颜色问题(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 11 章 颜色与对比】 ✔️ 11.1 通过对比进行交流 11.1.1 模式的建立11.1.2 还原设计稿 11.2 颜色的定义 11.2.1 色域与色彩空间11.2.2 CSS 颜色表示法 11.2.2.1 RGB…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...