Unity自定义后处理——Bloom效果

大家好,我是阿赵。
  继续介绍屏幕后处理效果,这一期讲一下Bloom效果。

一、Bloom效果介绍

在这里插入图片描述

还是拿这个模型作为背景。
在这里插入图片描述

Bloom效果,就是一种全屏泛光的效果,让模型和特效有一种真的在发光的感觉。

在这里插入图片描述
在这里插入图片描述

根据参数不一样,可以做出不同的发光效果。

二、原理介绍

  之前在介绍模糊效果的时候说过,Bloom效果也是基于模糊效果制作的。
  Bloom的原理很简单,先用模糊处理,算出一张模糊后的图片,然后把这张图片的RGB和原始屏幕图片的RGB相加就可以了。由于是RGB颜色叠加,所以本身图片颜色越接近白色的地方,越容易爆掉,所以越接近白色的地方发光的感觉就越明显。如果想Bloom的效果更爆一点,就自己对模糊后的图片进一步做处理吧,最常见的手段就是先乘后加,或者Power后再相加也可以
在这里插入图片描述

实现很简单,在原来的模糊效果代码上面,我们应该再加多一个叠加的Shader就可以了。

half4 frag (v2f_img i) : SV_Target
{half4 col = tex2D(_MainTex, i.uv);half4 brightCol = tex2D(_brightTex, i.uv);col.rgb += brightCol.rgb;return col;
}

  我这里在处理模糊之前,先加多了一个BrightRange的计算。这是为了控制一下发光的范围。BrightRange的算法很简单,先取原始图片的rgb三个通道颜色值最大的通道的值,然后用这个最大值减去一个我们指定的值。最后把原图的rgb颜色乘以这个值就可以了。

fixed4 frag (v2f_img i) : SV_Target
{fixed4 col = tex2D(_MainTex, i.uv);float br = max(max(col.r, col.g), col.b);br = max(0, (br - _BrightCut)) / max(br, 0.00001);col.rgb *= br;return col;
}

通过这个值,我们就可以更好的控制发光的范围
三、源码
1、C#部分

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BloomCtrl : MonoBehaviour
{private Material blurMat;private Material brightMat;private Material bloomMat;public bool isBlur = false;[Range(0, 4)]public float blurSize = 0;[Range(-3, 3)]public float blurOffset = 1;[Range(1, 3)]public int blurType = 3;[Range(0, 1)]public float brightCut = 0.5f;void Start(){}void Update(){}private Material GetBlurMat(int bType){if (bType == 1){return new Material(Shader.Find("Hidden/AzhaoBoxBlur"));}else if (bType == 2){return new Material(Shader.Find("Hidden/AzhaoGaussianBlur"));}else if (bType == 3){return new Material(Shader.Find("Hidden/AzhaoKawaseBlur"));}else{return null;}}private void ReleaseRT(RenderTexture rt){if (rt != null){RenderTexture.ReleaseTemporary(rt);}}private bool CheckNeedCreateBlurMat(Material mat, int bType){if (mat == null){return true;}if (mat.shader == null){return true;}if (bType == 1){if (mat.shader.name != "Hidden/AzhaoBoxBlur"){return true;}else{return false;}}else if (bType == 2){if (mat.shader.name != "Hidden/AzhaoGaussianBlur"){return true;}else{return false;}}else if (bType == 3){if (mat.shader.name != "Hidden/AzhaoKawaseBlur"){return true;}else{return false;}}else{return false;}}private void BlurFun(RenderTexture source, RenderTexture destination, float blurTime, int bType, float offset){if (CheckNeedCreateBlurMat(blurMat, bType) == true){blurMat = GetBlurMat(bType);}if (blurMat == null || blurMat.shader == null || blurMat.shader.isSupported == false){return;}blurMat.SetFloat("_BlurOffset", offset);float width = source.width;float height = source.height;int w = Mathf.FloorToInt(width);int h = Mathf.FloorToInt(height);RenderTexture rt1 = RenderTexture.GetTemporary(w, h);RenderTexture rt2 = RenderTexture.GetTemporary(w, h);Graphics.Blit(source, rt1);for (int i = 0; i < blurTime; i++){ReleaseRT(rt2);width = width / 2;height = height / 2;w = Mathf.FloorToInt(width);h = Mathf.FloorToInt(height);rt2 = RenderTexture.GetTemporary(w, h);Graphics.Blit(rt1, rt2, blurMat, 0);width = width / 2;height = height / 2;w = Mathf.FloorToInt(width);h = Mathf.FloorToInt(height);ReleaseRT(rt1);rt1 = RenderTexture.GetTemporary(w, h);Graphics.Blit(rt2, rt1, blurMat, 1);}for (int i = 0; i < blurTime; i++){ReleaseRT(rt2);width = width * 2;height = height * 2;w = Mathf.FloorToInt(width);h = Mathf.FloorToInt(height);rt2 = RenderTexture.GetTemporary(w, h);Graphics.Blit(rt1, rt2, blurMat, 0);width = width * 2;height = height * 2;w = Mathf.FloorToInt(width);h = Mathf.FloorToInt(height);ReleaseRT(rt1);rt1 = RenderTexture.GetTemporary(w, h);Graphics.Blit(rt2, rt1, blurMat, 1);}Graphics.Blit(rt1, destination);ReleaseRT(rt1);rt1 = null;ReleaseRT(rt2);rt2 = null;return;}private bool BrightRangeFun(RenderTexture source, RenderTexture destination){if (brightMat == null){brightMat = new Material(Shader.Find("Hidden/BrightRange"));}if (brightMat == null || brightMat.shader == null || brightMat.shader.isSupported == false){return false;}brightMat.SetFloat("_BrightCut", brightCut);Graphics.Blit(source, destination, brightMat);return true;}private bool BloomAddFun(RenderTexture source, RenderTexture destination, RenderTexture brightTex){if (bloomMat == null){bloomMat = new Material(Shader.Find("Hidden/AzhaoBloom"));}if (bloomMat == null || bloomMat.shader == null || bloomMat.shader.isSupported == false){return false;}bloomMat.SetTexture("_brightTex", brightTex);Graphics.Blit(source, destination, bloomMat);return true;}private void OnRenderImage(RenderTexture source, RenderTexture destination){if (isBlur == true){RenderTexture finalRt = source;RenderTexture rt2 = RenderTexture.GetTemporary(source.width, source.height);RenderTexture rt3 = RenderTexture.GetTemporary(source.width, source.height);BrightRangeFun(source, rt2);if (blurSize > 0){BlurFun(rt2, rt3, blurSize, blurType, blurOffset);BloomAddFun(source, finalRt, rt3);}Graphics.Blit(finalRt, destination);ReleaseRT(finalRt);ReleaseRT(rt2);ReleaseRT(rt3);}else{Graphics.Blit(source, destination);}}
}

2、Shader
  模糊shader就不重复了,参考之前的文章
这里提供一下Bloom和BrightRange的shader
1.Bloom

Shader "Hidden/AzhaoBloom"
{Properties{_MainTex ("Texture", 2D) = "white" {}_brightTex("BrightTex",2D) = "black"}SubShader{// No culling or depthCull Off ZWrite Off ZTest AlwaysPass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;sampler2D _brightTex;half4 frag (v2f_img i) : SV_Target{half4 col = tex2D(_MainTex, i.uv);half4 brightCol = tex2D(_brightTex, i.uv);col.rgb += brightCol.rgb;return col;}ENDCG}}
}

2.BrightRange

Shader "Hidden/BrightRange"
{Properties{_MainTex ("Texture", 2D) = "white" {}_BrightCut("LightVal",Range(0,1)) = 0.5}SubShader{// No culling or depthCull Off ZWrite Off ZTest AlwaysPass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;float _BrightCut;fixed4 frag (v2f_img i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv);float br = max(max(col.r, col.g), col.b);br = max(0, (br - _BrightCut)) / max(br, 0.00001);col.rgb *= br;return col;}ENDCG}}
}

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

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

相关文章

Packet Tracer – 实施静态 NAT 和动态 NAT

Packet Tracer – 实施静态 NAT 和动态 NAT 拓扑图 目标 第 1 部分&#xff1a;利用 PAT 配置动态 NAT 第 2 部分&#xff1a;配置静态 NAT 第 3 部分&#xff1a;验证 NAT 实施 第 1 部分&#xff1a; 利用 PAT 配置动态 NAT 步骤 1&#xff1a; 配置允许用于 NAT …

【基于CentOS 7 的iscsi服务】

目录 一、概述 1.简述 2.作用 3. iscsi 4.相关名称 二、使用步骤 - 构建iscsi服务 1.使用targetcli工具进入到iscsi服务器端管理界面 2.实现步骤 2.1 服务器端 2.2 客户端 2.2.1 安装软件 2.2.2 在认证文件中生成iqn编号 2.2.3 开启客户端服务 2.2.4 查找可用的i…

AJAX-day03-AJAX进阶

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 同步代码和异步代码 回调函数地狱 Promise - 链式调用 Promise 链式应用 async函数和await async函…

Stable Diffusion入门笔记(自用)

学习视频&#xff1a;20分钟搞懂Prompt与参数设置&#xff0c;你的AI绘画“咒语”学明白了吗&#xff1f; | 零基础入门Stable Diffusion保姆级新手教程 | Prompt关键词教学_哔哩哔哩_bilibili 1.图片提示词模板 2.权重&#xff08;提示词&#xff09; 无数字 (flower)//花的…

MQTT网关 5G物联网网关 PLC控制工业网关

MQTT网关&#xff0c;两个以上的节点之间通信的新型网关&#xff0c;网络节点之间通过互连来实现双向通信。支持PLC协议转MQTT&#xff0c;实现plc数据采集上云&#xff0c;物联网云平台对接&#xff0c;广泛应用于工业自动化plc远程监测控制。 计讯物联5G MQTT物联网网关TG463…

如何解决 Git 合并冲突

在遇到合并冲突时&#xff0c;请不要惊慌。通过一些娴熟的技巧协商&#xff0c;你可以解决任何冲突。 假设你和我正在共同编辑同一个名称为 index.html 的文件。我对文件进行了修改&#xff0c;进行了提交&#xff0c;并将更改推送到 Git 远程仓库。你也对同一个文件进行了修改…

酷雷曼无人机技能培训考试圆满举办

2023年7月18日、19日&#xff0c;以“向云端起航&#xff0c;让技术落地”为主题的酷雷曼无人机技能提升培训会在酷雷曼北京运营中心隆重举行&#xff0c;来自全国各地的众多合作商参加了本次培训&#xff0c;通过系统、全面的学习成功取得了专业无人机飞行员执照&#xff0c;为…

BEVDet 论文解读

BEVDet: High-Performance Multi-Camera 3D Object Detection in Bird-Eye-View 作者单位 PhiGent Robotics 目的 2D 的视觉感知在过去的几年里有了急速的发展&#xff0c;涌现出一些优秀的范式工作&#xff0c;这些工作有较高的性能&#xff0c;可扩展性&#xff0c;以及多…

【数学建模】--典型相关分析

典型相关分析&#xff08;Canonical Correlation analysis&#xff09;研究两组变量&#xff08;每组变量中都可能有多个指标&#xff09;之间相关关系的一种多元统计方法。它能够揭示出两组变量之间的内在联系。 例子&#xff1a; 典型相关分析定义&#xff1a; 列题分析&…

OpenCV自带的HAAR级联分类器对脸部(人脸、猫脸等)的检测识别

在计算机视觉领域&#xff0c;检测人脸等是一种很常见且非常重要的应用&#xff0c;我们可以先通过开放计算机视觉库OpenCV来熟悉这个人脸识别领域。另外OpenCV关于颜色的识别&#xff0c;可以查阅&#xff1a;OpenCV的HSV颜色空间在无人车中颜色识别的应用HSV颜色识别的跟踪实…

苹果账号被禁用怎么办

转载&#xff1a;苹果账号被禁用怎么办 目录 禁用的原因 解除Apple ID禁用 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UKQ1ILhC-1689932607373)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw)]​编辑 …

fiddler抓取,Android真机测试

1.配置Fiddler抓取并解密HTTPS包 Fiddler默认是不抓取HTTPS包的&#xff0c;需要进行相应的配置。 打开Fiddler&#xff0c;选择“Tools->Fiddler Options...” 2.在弹出的对话框中选择“HTTPS”选项卡&#xff1a; 3.勾选“Capture HTTPS CONNECTs”&#xff0c;接着勾选…

第三天 运维高级 MySQL主从复制

1.理解MySQL主从复制原理 1、master&#xff08;binlog dump thread&#xff09;主要负责Master库中有数据更新的时候&#xff0c;会按照binlog格式&#xff0c;将更新的事件类型写入到主库的binlog文件中。 2、I/O thread线程在Slave中创建&#xff0c;该线程用于请求Master&…

uniapp 微信小程序 Picker下拉列表数据回显问题

效果图&#xff1a; 1、template <template><view class"items select-box"><view class"items-text">品牌型号</view><picker change"bindBrandType" :value"brandIndex" :range"brandList"…

HTTP 什么样的响应才会被缓存

下面来讨论什么样的响应会被缓存&#xff0c;以及使用好已经缓存好的条件是什么。 缓存分为两步&#xff0c;首先将响应缓存下来&#xff0c;第二步将要发起一个请求的时候检查当前缓存是否可以使用缓存了的响应。 (1) 请求方法可以被缓存理解&#xff08;不只于 GET 方法&…

17 界面布局--登录界面

要点&#xff1a; 利用widgets做布局&#xff1a;水平&#xff0c;垂直&#xff0c;栅格 利用弹簧设置收缩 widget宽高比实际控件大很多&#xff1a;设置Fixed 如果需要去除其余边框间隙可以设置layout 将最小尺寸和最大尺寸设置为固定即为固定尺寸 设置窗口标题&#xff1a;wi…

SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter

1. 自动配置流程 导入starter依赖导入autoconfigure寻找类路径下 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件启动&#xff0c;加载所有 自动配置类 xxxAutoConfiguration 给容器中配置功能组件组件参数绑定到 属性类中。xxxPrope…

前端技术Vue学习笔记--001

前端技术Vue学习笔记 文章目录 前端技术Vue学习笔记1、Vue2和Vue3比较2、Vue简介3、Vue快速上手4、插值表达式{{}}5、Vue响应式特性6、Vue指令6.1、v-html指令6.2、v-show指令和v-if指令6.3、v-else指令和v-else-if指令6.4、v-on指令6.4.1、v-on指令基础6.4.2、v-on调用传参 6.…

Kubernetes_核心组件_kubelet_kubelet服务全解析(二)

文章目录 前言kubelet 架构kubelet 职责Node管理(节点管理)Pod管理 kubelet管理Podkubelet如何管理当前节点上所有Podkubelet三个端口kubelet获取Pod清单kubelet通过CRI接口管理Pod以及里面的容器 PodWorker的工作细节PodWorker的工作细节PLEG组件PLEG报错 kubelet创建并启动Po…

arcgis-利用等高线数据生成dem栅格

1、打开cass&#xff0c;展高程点&#xff0c;绘制三角网&#xff0c;绘制等高线&#xff0c;删除三角网和高程点。如下&#xff1a; 2、得到的等高线图&#xff0c;如下&#xff1a; 3、保存文件为dwg格式&#xff0c;随后打开arcmap软件&#xff0c;打开dwg的线层数据&#x…