【Unity】URP屏幕后处理UI模糊效果实现

 这里Canvas(1)设置为Overlay能渲染出指定UI高清,其他UI模糊,然而这做法非常不好,如果此时再打开UI 以及 关闭模糊效果 要将这些置顶UI 恢复到原本Canvas里,也就是要管理2套Canvas

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class Blur : ScriptableRendererFeature
{[Serializable] //序列化 会在ForwardRenderer下创建Blur时看到m_Data就是它public class BlurData{//blur材质public Material material;public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;//渲染次数,次数越大图像会越模糊[Range(0, 4)]public int iterations = 3;//模糊采样间距,越大越模糊[Range(0.2f, 3.0f)]public float blurSpread = 0.6f;//缩小比例(2代表缩小1/2) 越大越模糊,性能越好,但是会逐渐像素化![Range(1, 8)]public int downSample = 2;}public class BlurRenderPass : ScriptableRenderPass{private BlurData m_Data; //ForwardRenderer下Blur(ScriptableRendererFeature)资源的序列化参数数据private RenderTargetIdentifier m_Source;//屏幕图private RenderTargetHandle m_Buffer0;//缓冲区1private RenderTargetHandle m_Buffer1;//缓冲区2private int m_BlurSize = Shader.PropertyToID("_BlurSize");public BlurRenderPass(BlurData data){this.m_Data = data;}public void Setup(RenderTargetIdentifier cameraColorTarget){m_Buffer0.Init("_Buffer0");m_Buffer1.Init("_Buffer1");this.m_Source = cameraColorTarget;//该pass所在管线 ForwardRenderer 所处的摄像机主纹理}public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor){var width = cameraTextureDescriptor.width / m_Data.downSample;var height = cameraTextureDescriptor.height / m_Data.downSample;cmd.GetTemporaryRT(m_Buffer0.id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);cmd.GetTemporaryRT(m_Buffer1.id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);}public override void FrameCleanup(CommandBuffer cmd){cmd.ReleaseTemporaryRT(m_Buffer0.id);cmd.ReleaseTemporaryRT(m_Buffer1.id);}public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){var mat = m_Data.material;if (mat == null) return;//renderingData.cameraData.camera 可获取摄像机判定哪个摄像机才进行处理渲染(每个摄像机都会进一遍pass 如果摄像机有多个且都有这个Blur(ScriptableRendererFeature资源)CommandBuffer cmd = CommandBufferPool.Get("MyBlurCmd"); //从池获取一个cmd 命名为MyBlurCmd 能在FrameDebugger看到cmd.Blit(m_Source, m_Buffer0.Identifier());//将摄像机图渲染至buffer0//开始iterations次渲染,每次都会进行2次Pass操作:横向、纵向(谁先谁后都无所谓for (int i = 0; i < m_Data.iterations; i++){mat.SetFloat(m_BlurSize, 1.0f + i * m_Data.blurSpread);//指定采样间距,逐级递增的形式cmd.Blit(m_Buffer0.Identifier(), m_Buffer1.Identifier(), mat, 0);var tmp = m_Buffer0;m_Buffer0 = m_Buffer1; //注意最终都会将渲染结果输出到m_Buffer0m_Buffer1 = tmp;}cmd.Blit(m_Buffer0.Identifier(), m_Source); //将最终结果渲染到摄像机上//执行cmdcontext.ExecuteCommandBuffer(cmd);//清空回收cmdcmd.Clear();CommandBufferPool.Release(cmd);}}public BlurData data = new BlurData();private BlurRenderPass m_Pass;public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){var src = renderer.cameraColorTarget;m_Pass.Setup(src); //设置摄像机输出的颜色纹理renderer.EnqueuePass(m_Pass); //入队渲染pass}public override void Create(){m_Pass = new BlurRenderPass(data); //创建一个passm_Pass.renderPassEvent = data.renderPassEvent; //设置pass的渲染时机在某个节点后(导致问题,无法类似grab一样在某一个UI渲染时进行渲染 而必须等到所有UI渲染完成才进行渲染。。//无法做到置顶UI高清,底下UI模糊的效果.//所以下一步是思考如何实现这个吧..}
}

Shader代码实现模糊 

//注意 注释掉的CGINCLUDE CDEND UnityCG.cginc 等一系列带cg或注释的方法都是传统CG管线的内容
// 新内容会是HLSLxxx字眼形式出现 (目的是演示如何将CG代码改为URP管线代码)
Shader "MilkShader/Twently/G_GaussianBlur"
{Properties{_MainTex("Texture", 2D) = "white" {}//采样间距系数_BlurSize("Blur Size", Float) = 1.0}SubShader{Tags { "RenderType" = "Opaque" }LOD 100//CGINCLUDE ... ENDCG 是一种组织结构,放在它里面的方法可以被任意Pass直接使用..相当于所有Pass都会有这些内容//CGINCLUDE //CGHLSLINCLUDE//#include "UnityCG.cginc" //CG#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"sampler2D _MainTex;half4 _MainTex_TexelSize;float _BlurSize;//URP下没有appdata_img结构 要自定义struct a2v{float4 vertex : POSITION;float2 texcoord : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;half2 uv[5] : TEXCOORD0;};//我们只需要appdata_img内置结构的数据传入即可(有顶点、纹理坐标)v2f vertBlurVertical(a2v v) {v2f o;//o.pos = UnityObjectToClipPos(v.vertex); //CGVertexPositionInputs vertexInputs = GetVertexPositionInputs(v.vertex.xyz);o.pos = vertexInputs.positionCS;half2 uv = v.texcoord;//纵向的5个像素点纹理坐标o.uv[0] = uv;o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;return o;}v2f vertBlurHorizontal(a2v v) {v2f o;//o.pos = UnityObjectToClipPos(v.vertex); //CGVertexPositionInputs vertexInputs = GetVertexPositionInputs(v.vertex.xyz);o.pos = vertexInputs.positionCS;half2 uv = v.texcoord;//横向的5个像素点纹理坐标o.uv[0] = uv;o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;return o;}//无论是纵向还是横向,它们都会使用这个片元着色器,处理手法一样half4 fragBlur(v2f i) : SV_Target{float weight[3] = {0.4026, 0.2442, 0.0545};//采样RGB然后进行乘以对应的权重累加到sumhalf3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];for (int it = 1; it < 3; it++) {sum += tex2D(_MainTex, i.uv[it * 2 - 1]).rgb * weight[it];sum += tex2D(_MainTex, i.uv[it * 2]).rgb * weight[it];}//是的这样就完成了,模糊。。。。return half4(sum, 1.0);}//ENDCG //CGENDHLSL//上面都是INCLUDE内容即下面Pass都可使用的内容//标配写法ZTest Always Cull Off ZWrite Off//第一个PASS,纵向模糊处理Pass{NAME "GAUSSIAN_BLUR_VERTICAL"//CGPROGRAM //CGHLSLPROGRAM//纵向的顶点着色器#pragma vertex vertBlurVertical//片元着色器#pragma fragment fragBlur//ENDCG //CGENDHLSL}//第二个Pass 横向模糊处理Pass{NAME "GAUSSIAN_BLUR_HORIZONTAL"//CGPROGRAMHLSLPROGRAM//横向的顶点着色器#pragma vertex vertBlurHorizontal//片元着色器#pragma fragment fragBlur//ENDCGENDHLSL}}//完成SubShaderFallback Off
}

1个Canvas和2个摄像机

主要以上内容,实际上就是因为Render Pass Event是只能After Rendering Transpanrets在透明物体渲染完成后进行屏幕后处理模糊,导致无法实现置顶UI高清,底下UI模糊的需求,如果可以控制这个后处理时机是在置顶UI渲染之前进行后处理,等后处理完成后再渲染指定UI 那就可以,然而...

TODO!!!

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

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

相关文章

【算法与数据结构】404、LeetCode左叶子之和

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;思路比较简单&#xff0c;遍历所有节点然后判断该节点是否为左叶子节点&#xff0c;如果是&#xff0c…

windows11 利用vmware17 安装ky10-server-x86操作系统

下载相关软件和镜像 vmware17 下载 下载页面 Download VMware Workstation Pro ky10server-x86镜像下载 官网 国产操作系统、银河麒麟、中标麒麟、开放麒麟、星光麒麟——麒麟软件官方网站 (kylinos.cn) 选择对应版本去下载 安装 选择镜像&#xff0c;点击下一步 磁盘设置要…

ssm+vue宠物领养系统源码和论文

ssmvue宠物领养系统源码和论文103 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 本课题是根据用户的需要以及网络的优势建立的一个宠物领养系统&#xff0c;来满足用宠物领养的需求。 本宠物领养系统…

Android JNI系列详解之生成指定CPU的库文件

一、前提 这次主要了解Android的cpu架构类型&#xff0c;以及在使用CMake工具的时候&#xff0c;如何指定生成哪种类型的库文件。 如上图所示&#xff0c;是我们之前使用CMake工具默认生成的四种cpu架构的动态库文件&#xff1a;arm64-v8a、armeabi-v7a、x86、x86_64&#xff0…

5年测试在职经验之谈:2年功能测试、3年自动化测试,从入门到不可自拔...

毕业3年了&#xff0c;学的是环境工程专业&#xff0c;毕业后零基础转行做软件测试。 已近从事测试行业8年了&#xff0c;自己也从事过2年的手工测试&#xff0c;从事期间越来越觉得如果一直在手工测试的道路上前进&#xff0c;并不会有很大的发展&#xff0c;所以通过自己的努…

KVM虚拟化ubuntu

KVM&#xff08;Kernel-based Virtual Machine&#xff09;是一种基于Linux内核的虚拟化技术&#xff0c;它将Linux内核作为虚拟机的底层操作系统&#xff0c;利用硬件虚拟化支持创建和管理虚拟机。KVM虚拟化技术被广泛应用于云计算、虚拟化服务器、虚拟化桌面等场景。 KVM虚拟…

CodeBlocks20.03配置wxWidgets

背景 - 现在是2023年 1. 很多年前&#xff0c;下载使用CodeBlocks就发现里面有自带的wxWidgets Project的项目&#xff0c;然而一路Next下去出来的程序根本就不能运行&#xff0c;心有不甘&#xff1b; 2. 前几年&#xff0c;用python做小工具的时候&#xff0c;界面用的wxPy…

编程题四大算法思想(三)——贪心法:找零问题、背包问题、任务调度问题、活动选择问题、Prim算法

文章目录 贪心法找零问题&#xff08;change-making problem&#xff09;贪心算法要求基本思想适合求解问题的特征 背包问题0/1背包问题0/1背包问题——贪心法 分数背包问题 任务调度问题活动选择问题活动选择——贪心法最早结束时间优先——最优性证明 Prim算法 贪心法 我在当…

pytorch中nn.Conv1d功能介绍

在使用Conv1d函数时&#xff0c;pytorch默认你的数据是一维的&#xff0c;比如一句话“深度学习”可以用一个一维数组 [深, 度, 学, 习] 表示&#xff0c;这个数据就是一维的。图片是二维数据&#xff0c;它有长宽两个维度。 因此在使用 Conv1d 函数时&#xff0c;输入是一个三…

java八股文面试[多线程]——synchronized锁升级详细流程

偏向锁 偏向锁是JDK6中的重要引进&#xff0c;因为HotSpot作者经过研究实践发现&#xff0c;在大多数情况下&#xff0c;锁不仅不存在多线程竞争&#xff0c;而且总是由同一线程多次获得&#xff0c;为了让线程获得锁的代价更低&#xff0c;引进了偏向锁。 偏向锁是在单线程执…

表白墙程序

目录 一、页面代码部分 二、设计程序 二、实现 doPost​编辑 三、实现 doGet 四、前端代码部分 五、使用数据库存储数据 一、页面代码部分 在之前的一篇博客中&#xff0c;已经写过了表白墙的页面代码实现&#xff0c;这里就不再重复了 页面代码如下&#xff1a; <!…

ubuntu22安装和部署Kettle8.2

前提 kettle是纯java编写的etl开源工具&#xff0c;目前kettle7和kettle8都需要java8或者以上才能正常运行。所以运行kettle前先检查java环境是否正确配置&#xff0c;java版本是否是8或者以上。 kettle安装 1、创建kettle目录&#xff0c;并将kettle的zip包解压到kettle目…

linux开启端口

目录 1.查看防火墙状态 1.1 开启防火墙 1.2 再次查看防火墙状态 2.开启指定端口 3. 重启防火墙 4.重新加载防火墙 5.查看已经开启的端口 1.查看防火墙状态 firewall-cmd --state 如果返回的是 not running&#xff0c;那么需要先开启防火墙&#xff0c; 1.1 开启防火…

机器人中的数值优化(五)——信赖域方法

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

写的一款简易的热点词汇记录工具

项目需要对用户提交的附件、文章、搜索框内容等做热词分析。如下图&#xff1a; 公司有大数据团队。本着不麻烦别人就不麻烦别人的原则&#xff0c;写了一款简易的记录工具&#xff0c;原理也简单&#xff0c;手工在业务插入锚点&#xff0c;用分词器分好词&#xff0c;排掉字…

Ansible-playbook循环学习

循环语句简介 我们在编写playbook的时候&#xff0c;不可避免的要执行一些重复性操作&#xff0c;比如指安装软件包&#xff0c;批量创建用户&#xff0c;操作某个目录下的所有文件等。正如我们所说&#xff0c;ansible一门简单的自动化语言&#xff0c;所以流程控制、循环语句…

Ceph入门到精通-LVS基础知识

LB集群: &#xff08;Load Balancing&#xff09;即负载均衡集群,其目的是为了提高访问的并发量及提升服务器的性能&#xff0c;其 实现方式分为硬件方式和软件方式。 硬件实现方式&#xff1a; 常用的有 F5公司的BIG-IP系列、A10公司的AX系列、Citrix公司的 NetScaler系列…

VisualStudio配置pybind11-Python调用C++方法

个人测试下来Debug生成的dll改pyd&#xff0c;py中import会报错gilstate->autoInterpreterState 如果遇到同样问题使用Release吧 目录 1.安装pybind11 1.pip&#xff1a; 2.github&#xff1a; 2.配置VS工程 2.在VC目录中的包含目录添加&#xff1a; 3.在VC目录中的库目录…

【Web系列二十四】使用JPA简化持久层接口开发

目录 环境配置 1、引入依赖 配置文件 代码编写 实体类创建 JPA常用注解 Service与ServiceImpl Service ServiceImpl Controller Dao 三种实现Dao功能方式 1.继承接口&#xff0c;使用默认接口实现 2.根据接口命名规则默认生成实现 3.自定义接口实现(类似MyBatis…

汽车类 ±0.25°C SPI 温度传感器,TMP126EDBVRQ1、TMP126EDCKRQ1、TMP127EDBVRQ1引脚配置图

一、概述 TMP126-Q1 是一款精度为 0.25C 的数字温度传感器 &#xff0c; 支持的环境温度范围为 -55C 至 175C 。TMP126-Q1 具 有 14 位 &#xff08; 有符号 &#xff09; 温度分辨率(0.03125C/LSB)&#xff0c;并且可在 1.62V 至 5.5V 的电源电压范围内工作。TMP126-Q1 具有转…