Unity 实现部分物体Bloom效果

2024-01-15 11:08

本文主要是介绍Unity 实现部分物体Bloom效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前研究了一下怎么让屏幕里部分东西显示bloom效果,例如只是特效显示bloom效果而角色不显示,现在记录一下

我这里加了效果图和工程下载地址,方便大家了解

PS:这个性能有问题,建议看看这边博客,用存储alpha来替换重新渲染一遍带来的性能问题

https://blog.csdn.net/SnoopyNa2Co3/article/details/88075047

 

扩展:可以修改替换shader,把特定效果部分做成不同颜色区域来进行不同屏幕处理

例如:

渲染成红色作为bloom取图区来处理bloom效果

渲染绿色作为扭曲取图区来处理热扭曲效果

场景里部分实现bloom效果

这里之前先说一下Bloom的实现原理

一开始我们设置一个泛光的亮度阈值,然后我们根据屏幕的渲染图来进行筛选,所有小于这个阈值的像素过滤掉(黑色像素),其他像素保留,这样子就只保留了要发光的像素,其他的都是黑色泛光效果是由衍射效果产生的,我们现实世界中看到的泛光效果,最亮的地方实际上是会向暗的地方扩散的,也就是说在亮的地方,边界是不明显的,所以我们就需要对泛光是部分,也就是我们上一步操作的结果图片进行模糊操作,达到光溢出的效果,最后,我们将处理过的图像和原图像进行叠加,就得到了最终的效果。下面是bloom的实现流程图(盗图)

下面是部分Bloom实现原理

部分和上面全屏泛光的区别在于

全屏泛光:全屏泛光是那屏幕图像来处理泛光,然后和屏幕叠加

部分泛光:自己渲染一张特定的图,然后用这张图处理泛光,最后和屏幕叠加

区别在于这张特定的图,其他的和全屏泛光一样

如果分layer来渲染这张特定图,则没有遮挡效果,所以这种渲染可以放弃

这张特定图除了要泛光之外其余都要黑色也要走遮挡效果,所以用shader替换渲染方法来处理

 

泛光特定图获取

原理

获取泛光图要用到替换shader渲染方法

m_Camera.RenderWithShader(replaceShader, "RenderType");

这个替换shader是根据shader的标签RenderType来进行替换

除了repalceShader加了对应的替换标签

物体使用的shader也要加对应的标签,所以我这边直接拿原生的shader改一下标签

我这边自己加了“BloomTransparent”和“Bloom”标签(这些标签都是自己定义,自己知道直接写在shader上面)

BloomTransparent:适合渲染队列是Transparent的物体替换shader,对应物体shader改一下RenderType为“BloomTransparent”

Bloom:适合渲染队列是Opaque的物体替换shader,对应的shader改一下RenderType为“Bloom”

我举例一下自带的Mobile-Particle-Add,我这里顺便改一下名字,加了"RenderType"="BloomTransparent",如有需要还要改standar shader,这些看情况而定,这里只做个演示

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)// Simplified Additive Particle shader. Differences from regular Additive Particle one:
// - no Tint color
// - no Smooth particle support
// - no AlphaTest
// - no ColorMaskShader "Bloom/Particles/Additive" {
Properties {_MainTex ("Particle Texture", 2D) = "white" {}
}Category {Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="BloomTransparent" "PreviewType"="Plane" }Blend SrcAlpha OneCull Off Lighting Off ZWrite Off Fog{ Mode Off }BindChannels {Bind "Color", colorBind "Vertex", vertexBind "TexCoord", texcoord}SubShader {Pass {SetTexture [_MainTex] {combine texture * primary}}}
}
}

下面是替换shader

分了三种渲染

RenderType为Opaque直接渲染成黑色,

RenderType为Bloom直接渲染原图

RenderType为BloomTransparent按照混合模式渲染

其他直接渲染黑色

Shader "Hidden/Bloom Replace" 
{//替换标签是Bloom的shaderSubShader{Tags { "RenderType" = "Bloom" }Pass {CGPROGRAM#pragma vertex vert_img#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest#include "UnityCG.cginc"uniform sampler2D _MainTex;half4 frag(v2f_img i) : COLOR{return tex2D(_MainTex,i.uv);}ENDCG} }//替换标签是BloomTransparent的shaderSubShader{Tags{ "RenderType" = "BloomTransparent" }Blend SrcAlpha OneCull Off Lighting Off ZWrite Off Fog{ Mode Off }Pass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest#include "UnityCG.cginc"uniform sampler2D _MainTex;half4 frag(v2f_img i) : COLOR{return tex2D(_MainTex,i.uv);}ENDCG}}//替换标签是Opaque的shader,这里直接渲染为黑色SubShader {Tags { "RenderType" = "Opaque" }Pass {    CGPROGRAM#pragma vertex vert_img#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest#include "UnityCG.cginc"half4 frag(v2f_img i) : COLOR{return half4(0,0,0,0);}ENDCG}}   Fallback Off
}

RenderType为BloomTransparent和Bloom渲染出原来的颜色,其他没有标签则渲染成黑色,这样的泛光渲染图就这样出来了

下面是写了个脚本用来渲染泛光特定图

using UnityEngine;
using System.Collections;/// <summary>
/// 渲染需要广泛那部分的图
/// </summary>
public class RenderBloomTexture : MonoBehaviour
{/// <summary>/// 主摄像机/// </summary>public Camera m_FollowCamera;/// <summary>/// 渲染需要泛光的摄像机/// </summary>private Camera m_Camera;/// <summary>/// 替换shader/// </summary>public Shader replaceShader;void Start(){m_Camera = GetComponent<Camera>();//摄像机背景要设置为黑色m_Camera.enabled = false;m_Camera.clearFlags = CameraClearFlags.SolidColor;m_Camera.backgroundColor = Color.black;UpdateCamera();UpdateCameraSetting();}void LateUpdate(){UpdateCamera();//调用渲染m_Camera.RenderWithShader(replaceShader, "RenderType");}void UpdateCamera(){transform.position = m_FollowCamera.transform.position;transform.rotation = m_FollowCamera.transform.rotation;}void UpdateCameraSetting(){m_Camera.orthographic = m_FollowCamera.orthographic;m_Camera.orthographicSize = m_FollowCamera.orthographicSize;m_Camera.nearClipPlane = m_FollowCamera.nearClipPlane;m_Camera.farClipPlane = m_FollowCamera.farClipPlane;m_Camera.fieldOfView = m_FollowCamera.fieldOfView;}
}

使用

1.在场景的mian camera下面创建一个camera命名为“RenderCamera”,然后挂上RenderBloomTexture脚本

2.创建一个1920*1080的rendertexture,我这边做测试game视图分辨率和rendertexture一致都是1920*1080

3.把对应的以后shader拖上去和主摄像机拖上去,把新建的rendertexture拖到RenderCamera的TargetTexture,如下图

.

下面是对应物体设置的shader(这里的standard Shader改成加了标签Bloom改名为standardBloom)

4.直接运行然后看看RenderTexture,如下图有东西挡住就是ok的

泛光渲染图就这样实现出来

 

部分泛光实现

整个泛光实现我就不多说,网上多的是

先贴一下效果图

实现BloomEffect效果shader

Shader "BloomEffect" {Properties{_MainTex("Base (RGB)", 2D) = "white" {}_BlurTex("Blur", 2D) = "white"{}}CGINCLUDE
#include "UnityCG.cginc"//用于阈值提取高亮部分struct v2f_threshold{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;};//用于blurstruct v2f_blur{float4 pos : SV_POSITION;float2 uv  : TEXCOORD0;float4 uv01 : TEXCOORD1;float4 uv23 : TEXCOORD2;float4 uv45 : TEXCOORD3;};//用于bloomstruct v2f_bloom{float4 pos : SV_POSITION;float2 uv  : TEXCOORD0;float2 uv1 : TEXCOORD1;};sampler2D _MainTex;float4 _MainTex_TexelSize;sampler2D _BlurTex;float4 _BlurTex_TexelSize;float4 _offsets;float4 _colorThreshold;float4 _bloomColor;float _bloomFactor;//高亮部分提取shaderv2f_threshold vert_threshold(appdata_img v){v2f_threshold o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord.xy;//dx中纹理从左上角为初始坐标,需要反向
#if UNITY_UV_STARTS_AT_TOPif (_MainTex_TexelSize.y < 0)o.uv.y = 1 - o.uv.y;
#endif	return o;}fixed4 frag_threshold(v2f_threshold i) : SV_Target{fixed4 color = tex2D(_MainTex, i.uv);//仅当color大于设置的阈值的时候才输出return saturate(color - _colorThreshold);}//高斯模糊 vert shader(上一篇文章有详细注释)v2f_blur vert_blur(appdata_img v){v2f_blur o;_offsets *= _MainTex_TexelSize.xyxy;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord.xy;o.uv01 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1);o.uv23 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 2.0;o.uv45 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 3.0;return o;}//高斯模糊 pixel shader(上一篇文章有详细注释)fixed4 frag_blur(v2f_blur i) : SV_Target{fixed4 color = fixed4(0,0,0,0);color += 0.40 * tex2D(_MainTex, i.uv);color += 0.15 * tex2D(_MainTex, i.uv01.xy);color += 0.15 * tex2D(_MainTex, i.uv01.zw);color += 0.10 * tex2D(_MainTex, i.uv23.xy);color += 0.10 * tex2D(_MainTex, i.uv23.zw);color += 0.05 * tex2D(_MainTex, i.uv45.xy);color += 0.05 * tex2D(_MainTex, i.uv45.zw);return color;}//Bloom效果 vertex shaderv2f_bloom vert_bloom(appdata_img v){v2f_bloom o;//mvp矩阵变换o.pos = UnityObjectToClipPos(v.vertex);//uv坐标传递o.uv.xy = v.texcoord.xy;o.uv1.xy = o.uv.xy;
#if UNITY_UV_STARTS_AT_TOPif (_MainTex_TexelSize.y < 0)o.uv.y = 1 - o.uv.y;
#endif	return o;}fixed4 frag_bloom(v2f_bloom i) : SV_Target{//取原始清晰图片进行uv采样fixed4 ori = tex2D(_MainTex, i.uv1);//取模糊普片进行uv采样fixed4 blur = tex2D(_BlurTex, i.uv);//输出= 原始图像,叠加bloom权值*bloom颜色*泛光颜色fixed4 final = ori + _bloomFactor * blur * _bloomColor;return final;}ENDCGSubShader{//pass 0: 提取高亮部分Pass{ZTest OffCull OffZWrite OffFog{ Mode Off }CGPROGRAM
#pragma vertex vert_threshold
#pragma fragment frag_thresholdENDCG}//pass 1: 高斯模糊Pass{ZTest OffCull OffZWrite OffFog{ Mode Off }CGPROGRAM
#pragma vertex vert_blur
#pragma fragment frag_blurENDCG}//pass 2: Bloom效果Pass{ZTest OffCull OffZWrite OffFog{ Mode Off }CGPROGRAM
#pragma vertex vert_bloom
#pragma fragment frag_bloomENDCG}}
}

下面是控制Bloom效果脚本

using System;
using UnityEngine;
using System.Collections;public class PartBloom : MonoBehaviour
{//采样率public int samplerScale = 1;//高亮部分提取阈值public Color colorThreshold = Color.gray;//Bloom泛光颜色public Color bloomColor = Color.white;//Bloom权值[Range(0.0f, 1.0f)]public float bloomFactor = 0.5f;/// <summary>/// Bloom材质球/// </summary>public Material _Material;/// <summary>/// 特定渲染图/// </summary>public RenderTexture m_R;void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){RenderTexture temp1 = RenderTexture.GetTemporary(m_R.width, m_R.height, 0, m_R.format);RenderTexture temp2 = RenderTexture.GetTemporary(m_R.width, m_R.height, 0, m_R.format);//复制泛光图Graphics.Blit(m_R, temp1);//根据阈值提取高亮部分,使用pass0进行高亮提取_Material.SetVector("_colorThreshold", colorThreshold);Graphics.Blit(temp1, temp2, _Material, 0);//高斯模糊,两次模糊,横向纵向,使用pass1进行高斯模糊_Material.SetVector("_offsets", new Vector4(0, samplerScale, 0, 0));Graphics.Blit(temp2, temp1, _Material, 1);_Material.SetVector("_offsets", new Vector4(samplerScale, 0, 0, 0));Graphics.Blit(temp1, temp2, _Material, 1);//Bloom,将模糊后的图作为Material的Blur图参数_Material.SetTexture("_BlurTex", temp2);_Material.SetVector("_bloomColor", bloomColor);_Material.SetFloat("_bloomFactor", bloomFactor);//使用pass2进行景深效果计算,清晰场景图直接从source输入到shader的_MainTex中Graphics.Blit(source, destination, _Material, 2);//释放申请的RTRenderTexture.ReleaseTemporary(temp1);RenderTexture.ReleaseTemporary(temp2);}}
}

使用

1.先创建一个使用BloomEffect shader的材质球

2.把bloom控制脚本挂到mian camera上面,然后把材质球和rendertexture拖上去如下图

 

最后放出工程下载

1RenderBloomTexture是展示渲染泛光图

2PartBloom是实现部分bloom的demo

PS:rendertexure的生成应该动态生成出来,尺寸也要根据屏幕分辨率来计算,我这里只加了几个shader,看情况把官方的shader改一下,然后规定美术用那些shader,如果替换shader麻烦那就直接写工具替换就行

链接:https://pan.baidu.com/s/1AGcAWkVMufggPsF2ZEzvEw 
提取码:cvn1 

这篇关于Unity 实现部分物体Bloom效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/608685

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

KLayout ------ 旋转物体90度并做平移

KLayout ------ 旋转创建的物体 正文 正文 前段时间,有个小伙伴留言问我,KLayout 中如何旋转自己创建的物体,这里特来说明一下。 import pyapoly = pya.DPolygon([pya.DPoint(0, 0), pya.DPoint(0, 5), pya

以canvas方式绘制粒子背景效果,感觉还可以

这个是看到项目中别人写好的,感觉这种写法效果还可以,就存留记录下 就是这种的背景效果。如果想改背景颜色可以通过canvas.js文件中的fillStyle值改。 附上demo下载地址。 https://download.csdn.net/download/u012138137/11249872

echarts省份标注加散点效果

这个是安徽的效果图,鼠标移到红色标注或者对应的市区位置都会显示对应的数值。 先直接上代码: import anhuiMapJson from './anhui.json'getCoords: function(city) {var res = [];if (city != null) {for (var c in this.cityMap.features) {if (this.cityMa