【Unity UPR】造个获取深度法线纹理的轮子
描边需要深度+法线纹理的加持,效果才能达到最好,但URP下很多版本不支持直接获取_CameraNormalsTexture,而我本人也尝试了一下在12.1.7下偷懒直接拿SSAO里的Depth Normal图,
虽然也能实现吧,但是需要打开SSAO的同时,再在shader中加入指定的Tag为"DepthNormals"的Pass才能实现:
稍微有点麻烦,而且总有种用别人东西的感觉。
那就尝试一下自己动手吧!动手造一个获取深度法线纹理的轮子!
贴一下项目环境:
URP12.1.7
Unity2021.3.8f1
浅看两篇手动获取深度法线纹理的文章:URP深度法线纹理 - 简书 (jianshu.com)和雪风大佬的urp管线的自学hlsl之路 第二十四篇 科幻扫描效果后篇 - 哔哩哔哩 (bilibili.com),实现都是依靠build-in底下的shader,然后将绘制出来的纹理传递给URP下自己项目定义的shader使用。
1 定义RenderFeature获取法线深度图
这个是参考了上述的过程,说实话,内容太过复杂。只有不断多学习,多做,每次都好好做备注,总有一天会完全理解的:
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class DepthNormalsFeature : ScriptableRendererFeature
{// 定义3个共有变量public class Settings{//public Shader shader; // 设置后处理shaderpublic Material material; //后处理Materialpublic RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; // 定义事件位置,放在了官方的后处理之前}// 初始化一个刚刚定义的Settings类public Settings settings = new Settings();// 初始化PassDepthNormalsPass depthNormalsPass;// 初始化纹理RenderTargetHandle depthNormalsTexture;// 材质Material depthNormalsMaterial;// 给pass传递变量,并加入渲染管线中public override void Create(){// 通过Built-it管线中的Shader创建材质,最重要的一步!depthNormalsMaterial = CoreUtils.CreateEngineMaterial("Hidden/Internal-DepthNormalsTexture");// 获取Pass(渲染队列,渲染对象,材质)depthNormalsPass = new DepthNormalsPass(RenderQueueRange.opaque, -1, depthNormalsMaterial);// 设置渲染时机 = 预渲染通道后depthNormalsPass.renderPassEvent = RenderPassEvent.AfterRenderingPrePasses;// 设置纹理名depthNormalsTexture.Init("_CameraDepthNormalsTexture");}//这里你可以在渲染器中注入一个或多个渲染通道。//这个方法在设置渲染器时被调用。public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){// 对Pass进行参数设置(当前渲染相机信息,深度法线纹理)depthNormalsPass.Setup(renderingData.cameraData.cameraTargetDescriptor, depthNormalsTexture);// 写入渲染管线队列renderer.EnqueuePass(depthNormalsPass);}}public class DepthNormalsPass : ScriptableRenderPass
{int kDepthBufferBits = 32; // 缓冲区大小private RenderTargetHandle Destination { get; set; } // 深度法线纹理private Material DepthNormalsMaterial = null; // 材质private FilteringSettings m_FilteringSettings; // 筛选设置static readonly string m_ProfilerTag = "Depth Normals Pre Pass"; // 定义渲染TagShaderTagId m_ShaderTagId = new ShaderTagId("MyDepthOnly"); // 绘制标签,Shader需要声明这个标签的tag/// <summary>/// 构造函数Pass/// </summary>/// <param name="renderQueueRange"></param>/// <param name="layerMask"></param>/// <param name="material"></param>public DepthNormalsPass(RenderQueueRange renderQueueRange, LayerMask layerMask, Material material){m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);DepthNormalsMaterial = material;}/// <summary>/// 参数设置/// </summary>/// <param name="baseDescriptor"></param>/// <param name="Destination"></param>public void Setup(RenderTextureDescriptor baseDescriptor, RenderTargetHandle Destination){// 设置纹理this.Destination = Destination;}/// <summary>/// 配置渲染目标,可创建临时纹理/// </summary>/// <param name="cmd"></param>/// <param name="cameraTextureDescriptor"></param>public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor){// 设置渲染目标信息RenderTextureDescriptor descriptor = cameraTextureDescriptor;descriptor.depthBufferBits = kDepthBufferBits;descriptor.colorFormat = RenderTextureFormat.ARGB32;// 创建一个临时的RT(储存深度法线纹理、目标信息和滤波模式)cmd.GetTemporaryRT(Destination.id, descriptor, FilterMode.Point);// 配置ConfigureTarget(Destination.Identifier());// 清楚,未渲染时配置为黑色ConfigureClear(ClearFlag.All, Color.black);}// /// <summary>/// 后处理逻辑和渲染核心函数,相当于build-in 的OnRenderImage()/// 实现渲染逻辑/// </summary>/// <param name="context"></param>/// <param name="renderingData"></param>public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){var cmd = CommandBufferPool.Get(m_ProfilerTag); // 设置渲染标签using (new ProfilingSample(cmd, m_ProfilerTag)){// 执行命令缓存context.ExecuteCommandBuffer(cmd);// 清楚数据缓存cmd.Clear();// 相机的排序标志var sortFlags = renderingData.cameraData.defaultOpaqueSortFlags;// 创建绘制设置var drawSettings = CreateDrawingSettings(m_ShaderTagId, ref renderingData, sortFlags);// 设置对象数据drawSettings.perObjectData = PerObjectData.None;// 设置覆盖材质drawSettings.overrideMaterial = DepthNormalsMaterial;// 绘制渲染器context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref m_FilteringSettings);// 设置全局纹理cmd.SetGlobalTexture("_CameraDepthNormalsTexture", Destination.id);}// 执行命令缓冲区context.ExecuteCommandBuffer(cmd);CommandBufferPool.Release(cmd);}// 清除此呈现传递执行期间创建的任何已分配资源。public override void FrameCleanup(CommandBuffer cmd){if (Destination != RenderTargetHandle.CameraTarget){cmd.ReleaseTemporaryRT(Destination.id);Destination = RenderTargetHandle.CameraTarget;}}
}
2 在Shader中使用
上述RenderFeature我们获得了一个全局的_CameraDepthNormalsTexture变量,我们就可以像Build-in下一样访问啦!
但是,一些之前固定管线下的一些采样、解码Texture函数在URP下不能直接用,要自己定义,主要需要一个解码函数。固定管线下函数:
其中:
直接搬运!完全没问题~
我给他合起来了,合成了一个函数,返回的时候用就行:
还要注意,采样要是屏幕空间的UV,不然乱七八糟。
然后shader后面必须也要加上一个自定义的LightTag:
突然发现这个复杂程度跟SSAO那个差不多。。。
看看效果,我们单独输出深度和法线:
一切正常!终于可以进行下一步了。
参考
URP深度法线纹理 - 简书 (jianshu.com)
相关文章:

【Unity UPR】造个获取深度法线纹理的轮子
描边需要深度法线纹理的加持,效果才能达到最好,但URP下很多版本不支持直接获取_CameraNormalsTexture,而我本人也尝试了一下在12.1.7下偷懒直接拿SSAO里的Depth Normal图, 虽然也能实现吧,但是需要打开SSAO的同时&…...

用 Python解析HTML页面
用 Python 解析 HTML 页面 在网络爬取的过程中,我们通常需要对所爬取的页面进行解析,从中提取我们需要的数据。网页的结构通常是由 HTML 标签所组成的,通过对这些标签的解析,可以得到网页中所包含的有用信息。在 Python 中&#…...

python logging 详解
python logging 详解1. 导入logging模块2. 配置日志记录器3. 记录日志消息4. 自定义日志记录器5. 日志轮换6. 日志过滤器7. 日志异常跟踪8. 日志输出到控制台和文件9. 使用配置文件10. 使用第三方库11. format格式详解12. 总结Python的logging模块提供了灵活的日志记录功能&…...

( “树” 之 DFS) 687. 最长同值路径 ——【Leetcode每日一题】
687. 最长同值路径 给定一个二叉树的 root ,返回 最长的路径的长度 ,这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。 两个节点之间的路径长度 由它们之间的边数表示。 示例 1: 输入:root [5,4,5,1,1,5] 输出&…...

Elasticsearch解决不能修改索引、字段问题解决方案
问题1: 由于es索引不能删除,不能修改,在不影响原数据的情况下,并且生产服务不停机的情况下,怎么修改索引,并保留原索引内的数据? 基于kibanna的dev Tools执行参数,淘汰postman&…...

面试官在线改简历 | 只有6秒!程序员简历这样写才能抓住科技公司大佬的眼球
其实每一份简历 每一个瑞库特 可能也就平均花6秒钟的时间看一看 来进行一个快速的筛选 一份好的简历到底应该长什么样 同时呢在我们写简历的过程当中 应该避免什么样子的错误和误区 那我们今天呢来聊聊这个简历的事 大家知道 每次到了招聘高分期啊这些大的公司 像谷歌Facebook…...

IM即时通讯-7-如何设计通知提醒
本文大纲 本文从为什么做通知提醒, 以及如何设计通知提醒, 以及如何衡量通知提醒三方面解释了如何设计通知提醒。 对于重点的如何设计通知提醒, 通过拆分前台和后台, 前台采用自建或者二方通道, 后台采用厂商信令通道…...

赛狐ERP | 亚马逊选品方法与策略详解:如何挑选最优质的产品?
亚马逊作为全球电商巨头,其产品种类之丰富也是无人能及。然而,在如此繁杂的商品体系下,如何选品成为了摆在商家面前的一道难题。本文将从亚马逊选品的目标、方法、策略三个方面进行详细介绍。 一、选品的目标 在进行选择之前,必…...

【GCU体验】基于PyTorch + GCU跑通ResNet50模型并测试GCU性能
一、环境 地址:启智社区:https://openi.pcl.ac.cn/ 二、计算卡介绍 云燧T20是基于邃思2.0芯片打造的面向数据中心的第二代人工智能训练加速卡,具有模型覆盖面广、性能强、软件生态开放等特点,可支持多种人工智能训练场景。同时具备灵活的可…...

【机器视觉------标定篇(二)】三点成圆算法(求相机旋转中心)
应用场景 机器视觉项目应用中,相机安装在机器人上,并且需要定位产品返回坐标偏差以及角度偏差。 与九点标定配合使用,实现精准角度补偿。 算法输入 不共线的三点坐标 A(X₁,Y₁) ,B(X₂,Y₂&…...

AUTOSAR E2E详细介绍
E2E概述 E2E(End-To-End)是AUTOSAR为功能安全ISO26262提出的一个安全模块。这里的端(End)并不是指ECU与ECU之间,而是指通信ECU上的SW-C与SW-C之间。 在车载网络中,信息交换通常是从一个ECU发送信号,另一个ECU接收信号。对E2E而言,通常是从源SW-C生成信号,经过RTE(R…...

Dream 主题使用手册 - 基础篇
Dream 主题基于 Halo 博客系统开发,本文将介绍本主题一些功能的使用,文档将持续更新。 一、安装 & 更新 1.1 安装包安装 & 更新 进入主题 Release 界面:https://github.com/nineya/halo-theme-dream/releases 下载主题压缩包 halo…...

WSL下的Kafka开发容器:Docker搭建、API、整合
背景介绍 Kafka是一个分布式流处理平台,可以处理大规模数据流并支持实时数据流的处理。 本文介绍了如何在WSL下使用Docker搭建Kafka容器,并使用Python的kafka-python库和FastAPI框架实现了一个简单的API。同时,还将该服务整合到一个整体的d…...

cv2(OpenCV)下载安装
cv2对应库是OpenCV,官网下载链接:https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv 最好下载对应python版本的,通过pip命令安装可能会出现版本过高或者过低的问题,导致import cv2没问题,但是内部函数无法调用。 …...

【剑指 offer】旋转数组的最小数字
✨个人主页:bit me👇 ✨当前专栏:算法训练营👇 旋 转 数 组 的 最 小 数 字核心考点:数组理解,二分查找,临界条件 描述: 有一个长度为 n 的非降序数组,比如[1,2,3,4,5]…...

GB 9706.1-2020 医用电气设备第1部分:基本安全和基本性能的通用要求-1
这是份什么文件 这是一份中华人民共和国国家标准,具体为GB9706.1—2020,标准适用于医用电气设备,并规定了医用电气设备基本安全和基本性能的通用要求。主要涵盖了医疗电器设备与患者接触的各种要求,包括电气安全、机械防护、防护辐…...

认识C++《共、枚、指1》
目录 前言: 1.共用体的基本知识 2.匿名共用体 3.枚举 3.1设置枚举值 3.2枚举的应用场景 3.3枚举变量的取值范围 4.地址和自由存储空间 5.指针的思想 6.指针的声明和初始化 前言: 指针内容比较多,还需要再出一篇。久等了!!我看了我的…...

vim 一键配置
PS:本文是为了以后为了方便,做备忘的,今天用的时候找了半天很麻烦。 vim编辑器一键配置 在非root用户下执行上面的语句即可,不要在root用户下直接安装! 安装的时候需要输入root用户的密码,请找您的服主要一…...

如何成为一名成功的 PHP 开发者
当今的网络应用开发市场,PHP 一直是其中最受欢迎的语言之一,许多优秀的网络应用程序都是由 PHP 开发人员设计和开发的。如果你想成为一名成功的 PHP 开发者,以下是几个关键步骤: 1. 学习基础知识 首先,你需要掌握 PH…...

UHD安装教程
UHD Universal Hardware Driver,即USRP驱动。 UHD,Windows平台安装教程 uhd驱动安装 http://files.ettus.com/binaries/misc/erllc_uhd_winusb_driver.zip 安装LibUSBx http://files.ettus.com/binaries/uhd/latest_release 下载默认C盘 环境配置 将…...

Unity和UE有啥区别?哪个更适合游戏开发
游戏制作软件中最著名的两个游戏引擎是 Unity 和 Unreal Engine。从独立游戏到大型工作室,许多游戏开发商都在使用它们。如果你打算从事游戏行业工作,你肯定曾经问过自己“我的游戏应该使用 Unity 还是 Unreal Engine?” ” 让我们来了解和比…...

红队内网靶场
文章目录开篇介绍靶场介绍靶场下载以及配置Tomcat Get Shell突破DMZ防火墙拿下域内成员机器将内网机器上线到CS使用Adfind侦察子域信息控制子域DCRadmin登录子域进行权限维持(白银票据/ACL)子域bloodhound获取父域信息分析子域Krbtgt密钥创建跨域金票Dcsync父域PTH父域DC准备打…...

如何合并多个升序链表?
前言 本文主要介绍如何将多个小的升序链表合并一个大的升序链表。 需求描述 给出K个升序链接,要求把这K个升序链表合并成一个,并且这个链表也是升序的。 例如:A [1,5,6], B [2,3,8], C [4,4,9] 将这3个链表合并成一个链表D…...

23上半年信息系统项目管理师新老教程兼顾使用备考策略
在离考试仅有50多天的时候,软考办发文:“为方便报考信息系统项目管理师的考生进行复习备考,2023年上半年信息系统项目管理师考试第3版、第4版教程兼顾使用”。 其实软考办发布这样一条信息,也是为了照顾那些在新版发布以前按第…...

Linux环境搭建SVN服务器并实现公网访问 - cpolar端口映射
文章目录前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6.2 …...

仿牛客网社区Web开发项目代码逐行精读(更新中)
仿牛客网社区Web开发项目怎么看项目?如何调试项目前瞻技术架构项目亮点开始看代码LoginControllerDiscussPostController怎么看项目? pom.xml看技术架构resource看配置文件,这个项目是前后端不分离的以调试为导向,从前端入手检查…...

5G NR调制阶数与EVM关系以及对系统SNR要求分析
移动通信技术对数据传输速率要求越来越高。一种提高传输速率的思路是使用更高阶的QAM 调制方式,例如5G NR 的256QAM PDSCH,微波的1024QAM,2048QAM和4096QAM 调制。更高阶的QAM 调制方式对系统也提出了更高的要求。例如某个系统的EVM 测试结果…...

【NAS群晖drive异地访问】远程连接drive挂载电脑硬盘「内网穿透」
文章目录前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用3. 结语转发自CSDN远程穿透的文章:【群晖…...

react:hooks为什么不能写在条件语句里
背景 最近朋友在面试,说面试官问到了一个问题不会,说为什么 react hooks为什么不能写在条件语句里,今天我们来研究一下这个问题。 我们在来简单实现一个 useState: const reRender () > {stateIndex -1 ReactDOM.render(&…...

模型优势缺陷整理
(1)BERT 1. 计算资源消耗:bert模型是一个相对较大的模型,具有数亿个参数。因此,为了训练和使用bert模型,需要大量的计算资源和时间。 2. 学习不足问题:尽管bert模型在大规模语料库上进行了预训…...