注意别爆显存!!
原文地址:Unity UI背景模糊显示_wx667a71ca4e53b的技术博客_51CTO博客
原理就是提取相机拍摄画面,然后材质处理后再返回一个RenderTexture,然后赋值给RawImage,唯一缺点,就是如果释放不及时,容易爆显存。
BlurShader.shader
Shader "Unlit/BlurShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_BlurSize("BlurSize", Range(0, 127)) = 1.0
}
SubShader
{
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _MainTex_TexelSize;
fixed _BlurSize;
struct v2f{
float4 pos : SV_POSITION;
half2 uv[5] : TEXCOORD0;
};
// 水平uv数据扩展采样
v2f vert_hor(appdata_img v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
half2 uv = v.texcoord;
// 下标从0开始,分别取到当前像素,偏移1单位和2单位的uv位置
o.uv[0] = uv;
o.uv[1] = uv + half2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[2] = uv - half2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[3] = uv + half2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
o.uv[4] = uv - half2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
return o;
}
// 水平uv数据扩展采样
v2f vert_ver(appdata_img v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
half2 uv = v.texcoord;
// 下标从0开始,分别取到当前像素,偏移1单位和2单位的uv位置
o.uv[0] = uv;
o.uv[1] = uv + half2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[2] = uv - half2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[3] = uv + half2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
o.uv[4] = uv - half2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
return o;
}
// 处理模糊片元
fixed4 frag(v2f i) : SV_TARGET
{
// 模糊算子,分别决定了当前像素,上下(左右)偏移1个单位和2个单位的计算权重
// 算子决定了模糊的质量,算子越大越复杂效果越好,当然性能上就要差一些
half weight[3] = {0.4026, 0.2442, 0.0545};
// 当前像素片元颜色(乘以权重)
fixed3 color = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
// 根据权重叠加上下(左右)像素颜色
color += tex2D(_MainTex, i.uv[1]).rgb * weight[1];
color += tex2D(_MainTex, i.uv[2]).rgb * weight[1];
color += tex2D(_MainTex, i.uv[3]).rgb * weight[2];
color += tex2D(_MainTex, i.uv[4]).rgb * weight[2];
return fixed4(color, 1.0);
}
ENDCG
Cull Off
ZWrite Off
Pass // 0:处理水平模糊
{
Name "BLUR_HORIZONTAL"
CGPROGRAM
#pragma vertex vert_hor
#pragma fragment frag
ENDCG
}
Pass // 1:处理垂直模糊
{
Name "BLUR_VERTICAL"
CGPROGRAM
#pragma vertex vert_ver
#pragma fragment frag
ENDCG
}
}
Fallback Off
}BlurEffectMgr.cs
using UnityEngine;
public class BlurEffectMgr
{
private static BlurEffectMgr instance;
public static BlurEffectMgr Instance
{
get
{
if (instance == null)
instance = new BlurEffectMgr();
return instance;
}
}
private Camera Cam;
private RenderTexture blurRt;
RenderTexture tempRt;
public RenderTexture GetBlurRanderTexture(Camera Cam,Material blurMat,float blurLv = 1)
{
//Material blurMat = new Material(Resources.Load<Material>("Material/BlurEffect"));//这是刚刚创建的材质球
//Cam = GameObject.Find("Main Camera Full").GetComponent<Camera>();//用来获取相机的渲染画面
int width = Screen.width;
int height = Screen.height;
blurRt = RenderTexture.GetTemporary(width, height, 0);//尺寸我设置1/4,优化性能
Cam.targetTexture = blurRt;
Cam.Render();
Cam.targetTexture = null;
int count = 0;
tempRt = RenderTexture.GetTemporary(width, height, 0);//创建一张临时存放画面
while (count <= blurLv)//blurLv越大,画面越糊
{
blurMat.SetFloat("_BlurSize", (1.0f + count) * blurLv);
Graphics.Blit(blurRt, tempRt, blurMat, 0);
Graphics.Blit(tempRt, blurRt, blurMat, 1);
count++;
}
RenderTexture.ReleaseTemporary(tempRt);
return blurRt;
}
//不需要时,回收模糊背景图
public void ReleaseBlurRenderTexture()
{
RenderTexture.ReleaseTemporary(blurRt);
}
}TestView.cs
using System;
using UnityEngine;
using UnityEngine.UI;
public class TestView : MonoBehaviour
{
public RawImage BlurBg;
public Camera Camera;
public Material BlurMat;
public float BlurLv;
RenderTexture BlurRt;
void Start()
{
}
private void LateUpdate()
{
BlurRt?.Release();
BlurEffectMgr.Instance.ReleaseBlurRenderTexture();
BlurRt = BlurEffectMgr.Instance.GetBlurRanderTexture(Camera,BlurMat,BlurLv);//获取模糊图片
BlurBg.texture = BlurRt;
}
private void OnDisable()
{
}
}
评论