UnityShader 屏幕特效 模糊

时间:2021-12-18 00:59:36
  1. 上一篇文章写了屏幕特效必须的几个要素,这边通过一个 脚本继承与PostEffectsBase .以及通过shader 交互实现屏幕模糊特效。

  2. 下面通过添加在摄像机,引用3的shader。

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class Test : PostEffectsBase {

public Shader edgeDetectShader;
private Material edgeDetectMaterial = null;
public Material material
{
get
{
edgeDetectMaterial = CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial);
return edgeDetectMaterial;
}
}

[Range(0.0f, 1.0f)]
public float Parameter = 0.0f;

//类似Update,也是会不断通过输入,输出结果
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
if (material != null)
{
material.SetFloat("_BlurAmount", Parameter);
Graphics.Blit(src, dest, material);
}
else
{
Graphics.Blit(src, dest);
}
}
}

3.下面Shader

Shader "Futile/Blur"
{
Properties
{
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
_Color("Main Color", Color) = (0.2,0,1,1.5)
_BlurAmount("Blur Amount", Range(0,02)) = 0.0005
}

Category
{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }
ZWrite Off
//Alphatest Greater 0
Cull Off

SubShader
{
Pass
{

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma profileoption NumTemps=64
float4 _Color;
sampler2D _MainTex;
float _BlurAmount;

struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};

float4 _MainTex_ST;

v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}

half4 frag(v2f i) : COLOR
{
half4 texcol = half4(0,0,0,0);
float remaining = 1.0f;
float coef = 1.0;
float fI = 0;
for (int j = 0; j < 3; j++) {
fI++;
coef *= 0.32;
texcol += tex2D(_MainTex, float2(i.uv.x, i.uv.y - fI * _BlurAmount)) * coef;
texcol += tex2D(_MainTex, float2(i.uv.x - fI * _BlurAmount, i.uv.y)) * coef;
texcol += tex2D(_MainTex, float2(i.uv.x + fI * _BlurAmount, i.uv.y)) * coef;
texcol += tex2D(_MainTex, float2(i.uv.x, i.uv.y + fI * _BlurAmount)) * coef;

remaining -= 4 * coef;
}
//return texcol;

texcol += tex2D(_MainTex, float2(i.uv.x, i.uv.y)) * remaining;

return texcol;
}
ENDCG



}
}
}
}

4.简单介绍Category :就是同一个Shader,如果下面有多个Shader的话,都会套用下面这一套

    Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }
ZWrite Off
//Alphatest Greater 0
Cull Off

5.简单讲一下这个算法,这个通过在片元着色器进行上下左右进行像素微偏移

for (int j = 0; j < 3; j++) {
fI++;
coef *= 0.32;
texcol += tex2D(_MainTex, float2(i.uv.x, i.uv.y - fI * _BlurAmount)) * coef;
texcol += tex2D(_MainTex, float2(i.uv.x - fI * _BlurAmount, i.uv.y)) * coef;
texcol += tex2D(_MainTex, float2(i.uv.x + fI * _BlurAmount, i.uv.y)) * coef;
texcol += tex2D(_MainTex, float2(i.uv.x, i.uv.y + fI * _BlurAmount)) * coef;

remaining -= 4 * coef;
}

原图
UnityShader 屏幕特效 模糊
模糊图,通过调参数Parameter
UnityShader 屏幕特效 模糊
这边的Remaining为了 在下面保证迭代后基数为1。这样不会影响原本图像的亮度。比如这边基数默认设置10。就会锐化图像UnityShader 屏幕特效 模糊


总结
这边计算可以在顶点v2f vert(appdata_base v)里面计算,这样一位顶点计算量数比片元着色器计算更少。