145 lines
6.5 KiB
C#
145 lines
6.5 KiB
C#
using UnityEngine;
|
||
|
||
//设置在编辑模式下也执行该脚本
|
||
//[ExecuteInEditMode]
|
||
//添加选项到菜单中
|
||
[AddComponentMenu("RapidBlurEffect")]
|
||
public class RapidBlurEffectUtlis : MonoBehaviour
|
||
{
|
||
static class Uniforms
|
||
{
|
||
internal static readonly int _DownSampleValue = Shader.PropertyToID("_DownSampleValue");
|
||
}
|
||
|
||
//-------------------变量声明部分-------------------
|
||
#region Variables
|
||
|
||
//指定Shader名称
|
||
private string ShaderName = "Learning Unity Shader/Lecture 15/RapidBlurEffect";
|
||
public Shader CurShader;
|
||
|
||
//着色器和材质实例
|
||
private Material CurMaterial;
|
||
|
||
//降采样次数
|
||
[Range(0, 6), Tooltip("[降采样次数]向下采样的次数。此值越大,则采样间隔越大,需要处理的像素点越少,运行速度越快。")]
|
||
public int DownSampleNum = 2;
|
||
//模糊扩散度
|
||
[Range(0.0f, 20.0f), Tooltip("[模糊扩散度]进行高斯模糊时,相邻像素点的间隔。此值越大相邻像素间隔越远,图像越模糊。但过大的值会导致失真。")]
|
||
public float BlurSpreadSize = 2.0f;
|
||
//迭代次数
|
||
[Range(0, 8), Tooltip("[迭代次数]此值越大,则模糊操作的迭代次数越多,模糊效果越好,但消耗越大。")]
|
||
public int BlurIterations = 2;
|
||
|
||
#endregion
|
||
|
||
public void SetShader(Shader s)
|
||
{
|
||
CurShader = s;
|
||
}
|
||
|
||
Material material
|
||
{
|
||
get
|
||
{
|
||
if (CurMaterial == null && CurShader != null)
|
||
{
|
||
CurMaterial = new Material(CurShader);
|
||
CurMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||
}
|
||
return CurMaterial;
|
||
}
|
||
}
|
||
|
||
#region Functions
|
||
//-----------------------------------------【Start()函数】---------------------------------------------
|
||
// 说明:此函数仅在Update函数第一次被调用前被调用
|
||
//--------------------------------------------------------------------------------------------------------
|
||
void Start()
|
||
{
|
||
//判断当前设备是否支持屏幕特效
|
||
if (!SystemInfo.supportsImageEffects)
|
||
{
|
||
enabled = false;
|
||
return;
|
||
}
|
||
}
|
||
|
||
//-------------------------------------【OnRenderImage()函数】------------------------------------
|
||
// 说明:此函数在当完成所有渲染图片后被调用,用来渲染图片后期效果
|
||
//--------------------------------------------------------------------------------------------------------
|
||
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
|
||
{
|
||
//着色器实例不为空,就进行参数设置
|
||
if (material != null)
|
||
{
|
||
//【0】参数准备
|
||
//根据向下采样的次数确定宽度系数。用于控制降采样后相邻像素的间隔
|
||
float widthMod = 1.0f / (1.0f * (1 << DownSampleNum));
|
||
//Shader的降采样参数赋值
|
||
//material.SetFloat("_DownSampleValue", BlurSpreadSize * widthMod);
|
||
material.SetFloat(Uniforms._DownSampleValue, BlurSpreadSize * widthMod);
|
||
//设置渲染模式:双线性
|
||
sourceTexture.filterMode = FilterMode.Bilinear;
|
||
//通过右移,准备长、宽参数值
|
||
int renderWidth = sourceTexture.width >> DownSampleNum;
|
||
int renderHeight = sourceTexture.height >> DownSampleNum;
|
||
|
||
// 【1】处理Shader的通道0,用于降采样 ||Pass 0,for down sample
|
||
//准备一个缓存renderBuffer,用于准备存放最终数据
|
||
RenderTexture renderBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, sourceTexture.format);
|
||
//设置渲染模式:双线性
|
||
renderBuffer.filterMode = FilterMode.Bilinear;
|
||
//拷贝sourceTexture中的渲染数据到renderBuffer,并仅绘制指定的pass0的纹理数据
|
||
Graphics.Blit(sourceTexture, renderBuffer, material, 0);
|
||
|
||
//【2】根据BlurIterations(迭代次数),来进行指定次数的迭代操作
|
||
for (int i = 0; i < BlurIterations; i++)
|
||
{
|
||
//【2.1】Shader参数赋值
|
||
//迭代偏移量参数
|
||
float iterationOffs = (i * 1.0f);
|
||
//Shader的降采样参数赋值
|
||
//material.SetFloat("_DownSampleValue", BlurSpreadSize * widthMod + iterationOffs);
|
||
material.SetFloat(Uniforms._DownSampleValue, BlurSpreadSize * widthMod + iterationOffs);
|
||
|
||
// 【2.2】处理Shader的通道1,垂直方向模糊处理 || Pass1,for vertical blur
|
||
// 定义一个临时渲染的缓存tempBuffer
|
||
RenderTexture tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, sourceTexture.format);
|
||
// 拷贝renderBuffer中的渲染数据到tempBuffer,并仅绘制指定的pass1的纹理数据
|
||
Graphics.Blit(renderBuffer, tempBuffer, material, 1);
|
||
// 清空renderBuffer
|
||
RenderTexture.ReleaseTemporary(renderBuffer);
|
||
// 将tempBuffer赋给renderBuffer,此时renderBuffer里面pass0和pass1的数据已经准备好
|
||
renderBuffer = tempBuffer;
|
||
|
||
// 【2.3】处理Shader的通道2,竖直方向模糊处理 || Pass2,for horizontal blur
|
||
// 获取临时渲染纹理
|
||
tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, sourceTexture.format);
|
||
// 拷贝renderBuffer中的渲染数据到tempBuffer,并仅绘制指定的pass2的纹理数据
|
||
Graphics.Blit(renderBuffer, tempBuffer, material, 2);
|
||
|
||
//【2.4】得到pass0、pass1和pass2的数据都已经准备好的renderBuffer
|
||
// 再次清空renderBuffer
|
||
RenderTexture.ReleaseTemporary(renderBuffer);
|
||
// 再次将tempBuffer赋给renderBuffer,此时renderBuffer里面pass0、pass1和pass2的数据都已经准备好
|
||
renderBuffer = tempBuffer;
|
||
}
|
||
|
||
//拷贝最终的renderBuffer到目标纹理,并绘制所有通道的纹理到屏幕
|
||
Graphics.Blit(renderBuffer, destTexture);
|
||
//清空renderBuffer
|
||
RenderTexture.ReleaseTemporary(renderBuffer);
|
||
|
||
}
|
||
|
||
//着色器实例为空,直接拷贝屏幕上的效果。此情况下是没有实现屏幕特效的
|
||
else
|
||
{
|
||
//直接拷贝源纹理到目标渲染纹理
|
||
Graphics.Blit(sourceTexture, destTexture);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
} |