【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;//缓冲区1
        private RenderTargetHandle m_Buffer1;//缓冲区2

        private 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_Buffer0
                m_Buffer1 = tmp;
            }
            cmd.Blit(m_Buffer0.Identifier(), m_Source); //将最终结果渲染到摄像机上
            //执行cmd
            context.ExecuteCommandBuffer(cmd);
            //清空回收cmd
            cmd.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); //创建一个pass
        m_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 //CG
		HLSLINCLUDE
		//#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); //CG
			VertexPositionInputs 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); //CG
			VertexPositionInputs 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然后进行乘以对应的权重累加到sum
			half3 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 //CG
		ENDHLSL

		//上面都是INCLUDE内容即下面Pass都可使用的内容
		//标配写法
		ZTest Always Cull Off ZWrite Off
		//第一个PASS,纵向模糊处理
		Pass
		{
			NAME "GAUSSIAN_BLUR_VERTICAL"

			//CGPROGRAM //CG
			HLSLPROGRAM

			//纵向的顶点着色器
			#pragma vertex vertBlurVertical
			//片元着色器
			#pragma fragment fragBlur

			//ENDCG //CG
			ENDHLSL
		}
		//第二个Pass 横向模糊处理
		Pass
		{
			NAME "GAUSSIAN_BLUR_HORIZONTAL"

			//CGPROGRAM
			HLSLPROGRAM

			//横向的顶点着色器
			#pragma vertex vertBlurHorizontal
			//片元着色器
			#pragma fragment fragBlur

			//ENDCG
			ENDHLSL
		}
	}//完成SubShader
	Fallback Off
}

1个Canvas和2个摄像机

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

TODO!!!

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

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

相关文章

【仿写spring之ioc篇】二、bean生命周期中的创建以及属性赋值

扫描类 这个类就不多说了&#xff0c;基本所有框架都要有这一步&#xff0c;这里主要关注我们目前要实现的方法&#xff0c;其他的具体方法可以查看源码 isComponent方法 /*** 扫描所有带有Component注解的java类&#xff0c;放入到BeanRegistry** return boolean*/public bo…

以“迅”防“汛”!5G视频快线筑牢防汛“安全堤”

近期&#xff0c;西安多地突发山洪泥石流灾害。防洪救灾刻不容缓&#xff0c;为进一步做好防汛工作&#xff0c;加强防洪调度监管&#xff0c;切实保障群众的生命财产安全&#xff0c;当地政府管理部门亟需拓展智能化技术&#xff0c;通过人防技防双保障提升防灾救灾应急处置能…

无涯教程-Android - CheckBox函数

CheckBox是可以由用户切换的on/off开关。为用户提供一组互不排斥的可选选项时,应使用复选框。 CheckBox 复选框属性 以下是与CheckBox控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关方法。 继承自 android.widget.T…

Git企业开发控制理论和实操-从入门到深入(六)|多人协作开发

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

MTK6833_MT6833核心板_天玑700安卓5G核心板规格性能介绍

MTK6833安卓核心板采用台积电 7nm 制程的5G SoC&#xff0c;2*Cortex-A766*Cortex-A55架构&#xff0c;搭载Android12.0操作系统&#xff0c;主频最高达2.2GHz 。内置 5G 双载波聚合技术&#xff08;2CC&#xff09;及双 5G SIM 卡功能&#xff0c;实现优异的功耗表现及实时连网…

Watermark 是怎么生成和传递的?

分析&回答 Watermark 介绍 Watermark 本质是时间戳&#xff0c;与业务数据一样无差别地传递下去&#xff0c;目的是衡量事件时间的进度&#xff08;通知 Flink 触发事件时间相关的操作&#xff0c;例如窗口&#xff09;。 Watermark 是一个时间戳, 它表示小于该时间戳的…

Jenkins自动化部署-Jenkins的安装

首先我们需要安装docker 安装 yum-utils包 yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken 设置镜像地址 yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce…

【算法日志】动态规划刷题:股票买卖附加问题(day42)

代码随想录刷题60Day 目录 前言 含冷冻期的股票买卖最佳时期 含手续费的股票买卖最佳时期 前言 今天的股票买卖问题会附加一些条件&#xff0c;但总体难度不大。 含冷冻期的股票买卖最佳时期 该问题难点在于对几个状态进行解构并写出相应的状态转移方程。 int maxProfit(ve…

vue竖向步骤条

效果图&#xff1a; 弹框组件代码&#xff1a; <template><el-dialog:visible.sync"dialogVisible":append-to-body"true":close-on-click-modal"false":close-on-press-escape"false"titlewidth"8.2rem"custom-c…

pdf怎么转换成jpg图片?

随着数字文档的广泛应用&#xff0c;将PDF转换为JPG图片格式成为了一个常见的需求。无论是为了在网页上展示内容&#xff0c;还是为了与他人分享图片&#xff0c;以下是一些简单的方法&#xff0c;帮助您将PDF文件快速转换为高质量的JPG图片。 方法一&#xff1a;在线PDF转JPG…

ChatGPT对软件测试的影响

ChatGPT 是一个经过预训练的 AI 语言模型&#xff0c;可以通过聊天的方式回答问题&#xff0c;或者与人闲聊。它能处理的是文本类的信息&#xff0c;输出也只能是文字。它从我们输入的信息中获取上下文&#xff0c;结合它被训练的大模型&#xff0c;进行分析总结&#xff0c;给…

Elasticsearch 优化

Elasticsearch 优化 2.1硬件选择 Elasticsearch 的基础是 Lucene &#xff0c;所有的索引和文档数据是存储在本地的磁盘中&#xff0c;具体的 路径可在 ES 的配置文件 ../config/elasticsearch.yml 中配置&#xff0c;如下&#xff1a; #----------------------------…

2023年高教社杯数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…

【taro react】(游戏) ---- 贪吃蛇

1. 预览 2. 实现思路 实现食物类&#xff0c;食物坐标和刷新食物的位置&#xff0c;以及获取食物的坐标点&#xff1b;实现计分面板类&#xff0c;实现吃食物每次的计分以及积累一定程度的等级&#xff0c;实现等级和分数的增加&#xff1b;实现蛇类&#xff0c;蛇类分为蛇头和…

初阶数据结构(六)队列的介绍与实现

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn&#x1f493; ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的学习足迹&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 栈 队列的介绍队列的概念&#xff1a;队…

C++设计模式_02_面向对象设计原则

文章目录 1. 面向对象设计&#xff0c;为什么&#xff1f;2. 重新认识面向对象3. 面向对象设计原则3.1 依赖倒置原则(DIP)3.2 开放封闭原则(OCP )3.3 单一职责原则( SRP )3.4 Liskov 替换原则 ( LSP )3.5 接口隔离原则 ( ISP )3.6 优先使用对象组合&#xff0c;而不是类继承3.7…

【算法日志】动态规划刷题:股票买卖问题(day41)

代码随想录刷题60Day 目录 前言 买卖股票的最佳时机1 买卖股票的最佳时机2 买卖股票的最佳时机3 买卖股票的最佳时机4 前言 本日着重于多状态问题的处理&#xff0c;各状态之间会有一定联系&#xff0c;状态转移方程将不再局限一个。 买卖股票的最佳时机1 int maxProfit(…

RHCE——九、SELinux

SELinux 一、概念1、作用2、SELinux与传统的权限区别 二、SELinux工作原理1、名词解释主体&#xff08;Subject&#xff09;目标&#xff08;Object&#xff09;策略&#xff08;Policy&#xff09;安全上下文&#xff08;Security Context&#xff09; 2、文件安全上下文查看1…

[ZenTao]源码阅读:自定义任务类型

1、module/custom/control.php 2、module/custom/model.php

php开发环境搭建_宝塔、composer

宝塔面板下载&#xff0c;免费全能的服务器运维软件 一 下载宝塔面板 解压安装 登录之后修改安全入口 1 进入软件商店下载nginx,mysql5.6,php7.2 2 将php的安装路径配置到环境变量中 此电脑--右键--点击属性---高级系统设置---环境变量---系统变量path---添加确定 输入php -v…