深度和法线纹理

屏幕后期处理效果的基本原理就是当游戏画面渲染完毕后通过获取到该画面的信息进行额外的效果处理 之前的边缘检测、高斯模糊、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 update
    void Start()
    {
        Camera.main.depthTextureMode = DepthTextureMode.Depth;   
    }
}
Shader "ShaderProj/13/DepthTexture"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            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 update
    void Start() 
    {
        Camera.main.depthTextureMode = DepthTextureMode.DepthNormals;
    }
}
Shader "ShaderProj/13/DepthNormalTexture"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            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 轴:朝向反向向,蓝色)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3小兔鲜电商项目

创建项目 npm install 装包 创建文件夹 git工具管理项目 基于create-vue创建出来的项目默认没有初始化git仓库,需要我们手动初始化 执行命令并完成首次提交: git init git add . git commit -m "init"

短视频矩阵系统SEO优化排名技术的源码搭建与实施:

在开发短视频SEO优化排名技术时,虽然初步观察可能让人认为仅通过get和set这两个代理(trap)就能实现,但实际操作中远不止如此。为了更全面地控制私有属性的访问权限,还需要实现has、ownKeys以及getOwnPropertyDescripto…

Ubuntu中安装配置交叉编译工具并进行测试

01-下载获取交叉编译工具的源码 按照博文 https://blog.csdn.net/wenhao_ir/article/details/144325141的方法,把imx6ull的BSP下载好后,其中就有交叉编译工具。 当然,为了将来使用方便,我已经把它压缩并传到了百度网盘&#xff…

Fiddler 5.21.0 使用指南:过滤浏览器HTTP(S)流量下(四)

概述 在上一篇文章中,我们介绍了一部分简单的过滤功能,已经可以帮助我们较为准确的定位到感兴趣的请求;提升我们的工作效率,我们可以通过设置更为复杂的过滤规则,精准到定位的我们想要的请求和响应信息。专注于分析对…

错题:Linux C语言

题目&#xff1a;手写代码&#xff1a;判断一个数&#xff08;int类型的整数&#xff09;中有有多少1 题目&#xff1a;手写代码&#xff1a;判断一个数(转换成二进制表示时)有几个1 #include <stdio.h> int main(int argc, const char *argv[]) { //判断一个数&#xf…

MFC扩展库BCGControlBar Pro v36.0新版亮点:黑色主题中的自动反转图标

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v36.0已全新发布了&#xff0c;这个版本在黑暗主题中添加自动图标反转、新增一个全新的S…

【PlantUML系列】流程图(四)

目录 目录 一、基础用法 1.1 开始和结束 1.2 操作步骤 1.3 条件判断 1.4 并行处理 1.5 循环 1.6 分区 1.7 泳道 一、基础用法 1.1 开始和结束 开始一般使用start关键字&#xff1b;结束一般使用stop/end关键字。基础用法包括&#xff1a; start ... stopstart ...…

【Redis】深入解析Redis缓存机制:全面掌握缓存更新、穿透、雪崩与击穿的终极指南

文章目录 一、Redis缓存机制概述1.1 Redis缓存的基本原理1.2 常见的Redis缓存应用场景 二、缓存更新机制2.1 缓存更新的策略2.2 示例代码&#xff1a;主动更新缓存 三、缓存穿透3.1 缓存穿透的原因3.2 缓解缓存穿透的方法3.3 示例代码&#xff1a;使用布隆过滤器 四、缓存雪崩4…

LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略

LLMs之Agent之Lares&#xff1a;Lares的简介、安装和使用方法、案例应用之详细攻略 导读&#xff1a;这篇博文介绍了 Lares&#xff0c;一个由简单的 AI 代理驱动的智能家居助手模拟器&#xff0c;它展现出令人惊讶的解决问题能力。 >> 背景痛点&#xff1a;每天都有新的…

快速集成外部业务数据:观测云如何颠覆传统监控的边界

01 传统监控的局限&#xff1a;被困在技术的“象牙塔” 过去的监控工具更多地服务于 IT 技术人员&#xff0c;就像是只为运维人员准备的“秘密花园”。服务器负载、网络延迟、系统资源——这些技术指标构成了一个封闭的世界&#xff0c;与业务层隔绝&#xff0c;就像是运维人员…

如何在Ubuntu中利用repo和git地址下载获取imx6ull的BSP

01-设置git的用户名和邮箱 git config --global user.name "suwenhao" git config --global user.email "2487872782qq.com"这里不设置的话后面在第5步的repo配置中还是会要求输入&#xff0c;而且以后进行相关操作都要输入&#xff0c;不妨现在就进行配置…

Linux-Ubuntu相关指令以及操作

一&#xff0c;Linux基础指令 二&#xff0c;文件系统结构 常用的U盘就是挂载在这个mdeia文件夹下&#xff0c;比如实现优盘分几个区&#xff0c;就要将在dev下优盘的驱动解除挂载在media,然后对其进行分区&#xff0c;再挂载回去&#xff0c;最后将其类型重新改为fat32格式&am…

二进制部署Prometheus+grafana+alertmanager+node_exporter

Prometheus 是一个开源的监控和告警工具包&#xff0c;旨在提供高可靠性和可扩展性。它最初由 SoundCloud 开发&#xff0c;现已成为云原生计算基金会&#xff08;CNCF&#xff09;的一部分。以下是 Prometheus 的一些关键特性和概念&#xff1a; 1. **时间序列数据库**&#…

使用springboot-3.4.1搭建一个netty服务并且WebSocket消息通知(适用于设备直连操作,以及回复操作)

引入最新版本 <!--websocket--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>启动类加入 //netty 协议服务端口启动 NettyTcpHandler.start()…

vulnhub靶场【hacksudo】之2

前言 靶机&#xff1a;hacksudo-2 攻击&#xff1a;kali 都是采用虚拟机&#xff0c;网卡为桥接模式 主机发现 使用arp-scan -l或者netdiscover -r 192.168.1.1/24或者nmap和masscan等可以扫描网段的扫描工具&#xff0c;不过建议使用前两个即可&#xff0c;因为靶机与攻击…

Spring Boot助力,一键解锁招聘全流程信息精细化管理

2系统相关技术 2.1 Java语言介绍 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备了显著的优势和广阔的前景&#…

【设计模式系列】策略模式(二十四)

一、什么是策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是软件设计模式中的一种行为型模式。它定义了一系列算法&#xff0c;并将每一个算法封装起来&#xff0c;使它们可以互换使用&#xff0c;算法的变化不会影响使用算法的用户。策略模式让算法的变化独立于…

《Java核心技术I》映射条目的原子更新

映射条目的原子更新 ConcurrentHashMap只有部分原子更新。 JavaAPI提供了一些新方法&#xff0c;例如&#xff1a;compute方法可以提供一个键和一个计算新值的函数。 map.compute(word,(k,v)->v null ? 1 : v1) 注释&#xff1a;ConcurrentHashMap中不允许有null值。很…

【Rive】波动文字

1 前言 本文将使用文本修改器&#xff08;Text Modifiers&#xff09;做文字动画&#xff0c;实现文字波动效果。 按以下步骤可以创建一个 Modifier Group 和 Range。 部分参数的释义如下。 Range: Modifier 作用的范围。Falloff: Modifier 在最大值时的范围&#xff0c;Fallo…

《庐山派从入门到...》初见

《庐山派从入门到...》初见 庐山派简介立创庐山派资源网站 庐山派个人分享&#xff0c;主要内容放到视频中&#xff0c;视频主要流程截图在博客上&#xff0c;所使用链接和代码也会放到博客中方便提取。希望小伙伴给我的视频点个关注谢谢小伙伴们。 《庐山派从入门到...》初见 …