支持iOS、大部分Android平台的移动设备
.shader文件
Shader "Custom/ImageEffect_GaussianBlur" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
uniform half4 _MainTex_TexelSize;
uniform float _blurSize;
// weight curves
static const half curve[4] = { 0.0205, 0.0855, 0.232, 0.324};
static const half4 coordOffs = half4(1.0h,1.0h,-1.0h,-1.0h);
struct v2f_withBlurCoordsSGX
{
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
half4 offs[3] : TEXCOORD1;
};
v2f_withBlurCoordsSGX vertBlurHorizontalSGX (appdata_img v)
{
v2f_withBlurCoordsSGX o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
half2 netFilterWidth = _MainTex_TexelSize.xy * half2(1.0, 0.0) * _blurSize;
half4 coords = -netFilterWidth.xyxy * 3.0;
o.offs[0] = v.texcoord.xyxy + coords * coordOffs;
coords += netFilterWidth.xyxy;
o.offs[1] = v.texcoord.xyxy + coords * coordOffs;
coords += netFilterWidth.xyxy;
o.offs[2] = v.texcoord.xyxy + coords * coordOffs;
return o;
}
v2f_withBlurCoordsSGX vertBlurVerticalSGX (appdata_img v)
{
v2f_withBlurCoordsSGX o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
half2 netFilterWidth = _MainTex_TexelSize.xy * half2(0.0, 1.0) * _blurSize;
half4 coords = -netFilterWidth.xyxy * 3.0;
o.offs[0] = v.texcoord.xyxy + coords * coordOffs;
coords += netFilterWidth.xyxy;
o.offs[1] = v.texcoord.xyxy + coords * coordOffs;
coords += netFilterWidth.xyxy;
o.offs[2] = v.texcoord.xyxy + coords * coordOffs;
return o;
}
half4 fragBlurSGX ( v2f_withBlurCoordsSGX i ) : SV_Target
{
half2 uv = i.uv;
half4 color = tex2D(_MainTex, i.uv) * curve[3];
color += (tex2D(_MainTex, i.offs[0].xy) + tex2D(_MainTex, i.offs[0].zw)) * curve[0];
color += (tex2D(_MainTex, i.offs[1].xy) + tex2D(_MainTex, i.offs[1].zw)) * curve[1];
color += (tex2D(_MainTex, i.offs[2].xy) + tex2D(_MainTex, i.offs[2].zw)) * curve[2];
return color;
}
ENDCG
SubShader {
ZTest Off ZWrite Off Blend Off
Pass {
ZTest Always
CGPROGRAM
#pragma vertex vertBlurVerticalSGX
#pragma fragment fragBlurSGX
ENDCG
}
Pass {
ZTest Always
CGPROGRAM
#pragma vertex vertBlurHorizontalSGX
#pragma fragment fragBlurSGX
ENDCG
}
}
FallBack Off
}
.cs文件,挂载在摄像机上
using System.Collections;
using UnityEngine;
[ExecuteInEditMode]
public class ImageEffect_GaussianBlur : MonoBehaviour
{
#region Variables
[SerializeField]
private Shader gaussianBlurShader = null;
private Material BlurBoxMaterial = null;
[Range(0.0f, 1.0f)]
public float BlurSize = 0.5f;
public void AnimSetBlurSize(float from, float target, float time)
{
_Main.Stop(routineAnimSetBlurSize);
routineAnimSetBlurSize = RoutineAnimSetBlurSize(from, target, time);
_Main.Do(routineAnimSetBlurSize);
}
IEnumerator routineAnimSetBlurSize;
IEnumerator RoutineAnimSetBlurSize(float from, float target, float time)
{
float temp = 0;
while (temp < time)
{
BlurSize = Mathf.Lerp(from, target, temp / time);
yield return null;
temp += Time.deltaTime;
}
BlurSize = target;
}
#endregion
#region Properties
Material material
{
get
{
if (BlurBoxMaterial == null)
{
BlurBoxMaterial = new Material(gaussianBlurShader);
BlurBoxMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return BlurBoxMaterial;
}
}
#endregion
void OnEnable()
{
//高度适配
rate = Screen.height / 512f;
// Disable if we don't support image effects
if (!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}
// Disable the image effect if the shader can't
// run on the users graphics card
if (!gaussianBlurShader || !gaussianBlurShader.isSupported)
enabled = false;
return;
}
private float rate = 2;
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
if (BlurSize != 0 && gaussianBlurShader != null)
{
int rtW = (int)(sourceTexture.width / rate);
int rtH = (int)(sourceTexture.height / rate);
RenderTexture rtTempA = RenderTexture.GetTemporary(rtW, rtH, 0, sourceTexture.format);
rtTempA.filterMode = FilterMode.Bilinear;
Graphics.Blit(sourceTexture, rtTempA);
for (int i = 0; i < 2; i++)
{
// float iteraionOffs = i * 1.0f;
material.SetFloat("_blurSize", BlurSize);
//vertical blur
RenderTexture rtTempB = RenderTexture.GetTemporary(rtW, rtH, 0, sourceTexture.format);
rtTempB.filterMode = FilterMode.Bilinear;
Graphics.Blit(rtTempA, rtTempB, material, 0);
RenderTexture.ReleaseTemporary(rtTempA);
rtTempA = rtTempB;
//horizontal blur
rtTempB = RenderTexture.GetTemporary(rtW, rtH, 0, sourceTexture.format);
rtTempB.filterMode = FilterMode.Bilinear;
Graphics.Blit(rtTempA, rtTempB, material, 1);
RenderTexture.ReleaseTemporary(rtTempA);
rtTempA = rtTempB;
}
Graphics.Blit(rtTempA, destTexture);
RenderTexture.ReleaseTemporary(rtTempA);
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}
}
#if UNITY_EDITOR
// Update is called once per frame
void Update()
{
rate = Screen.height / 512f;
}
#endif
public void OnDisable()
{
if (BlurBoxMaterial)
DestroyImmediate(BlurBoxMaterial);
}
}