實作思路:離中心點越遠的像素 模糊效果越明顯 UV偏移的量越大
shader
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "3D/ScreenEdgeBlur" {
//------------------------------------【屬性值】------------------------------------
Properties
{
_MainTex("主紋理 (RGB)", 2D) = "white" {}
_IterationNumber("迭代次數", Int)=16
}
//------------------------------------【唯一的子著色器】------------------------------------
SubShader
{
//--------------------------------唯一的通道-------------------------------
Pass
{
//設定深度測驗模式:渲染所有像素.等同于關閉透明度測驗(AlphaTest Off)
ZTest Always
//===========開啟CG著色器語言撰寫模塊===========
CGPROGRAM
//編譯指令: 指定著色器編譯目標為Shader Model 3.0
#pragma target 3.0
//編譯指令:告知編譯器頂點和片段著色函式的名稱
//vert_img是在UnityCG.cginc中定義好的,當后處理vert階段計算常規,可以直接使用自帶的vert_img
#pragma vertex vert_img
#pragma fragment frag_blur
//包含輔助CG頭檔案
#include "UnityCG.cginc"
//外部變數的宣告
uniform sampler2D _MainTex;
uniform float _Value;
uniform float _Value2;
uniform float _Value3;
uniform int _IterationNumber;
float4 frag_blur(v2f_img i) : SV_TARGET
{
//【2】獲取紋理坐標的x,y坐標值
float2 uv = i.uv;
//【3】紋理坐標按照中心位置進行一個偏移
uv -= _center;
//【4】初始化一個顏色值
float4 color = float4(0.0, 0.0, 0.0, 0.0);
//【6】設定坐標縮放比例的值
float scale = 1;
//【7】進行紋理顏色的迭代
for (int j = 1; j < _IterationNumber; ++j)
{
//將主紋理在不同坐標采樣下的顏色值進行迭代累加
color += tex2D(_MainTex, uv * scale + _center);
//坐標縮放比例依據回圈引數的改變而變化
scale = 1 + (float(j * 0.02));
}
//【8】將最終的顏色值除以迭代次數,取平均值
color /= (float)_IterationNumber;
return color;
}
//===========結束CG著色器語言撰寫模塊===========
ENDCG
}
}
}
C#
using UnityEngine;
using System.Collections;
using XLua;
namespace bgdust
{
[ExecuteInEditMode]
public class ScreenBlurEffect : MonoBehaviour
{
//-------------------變數宣告部分-------------------
#region Variables
public Shader CurShader;//著色器實體
private Material CurMaterial;//當前的材質
[Range(2, 50)]
public float IterationNumber = 15;
public Vector2 center = new Vector2(0.5f, 0.5f);
public static Vector2 ChangeValue;
public static float ChangeValue2;
#endregion
//-------------------------材質的get&set----------------------------
#region MaterialGetAndSet
Material material
{
get
{
if (CurMaterial == null)
{
CurMaterial = new Material(CurShader);
CurMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return CurMaterial;
}
}
#endregion
//-----------------------------------------【Start()函式】---------------------------------------------
// 說明:此函式僅在Update函式第一次被呼叫前被呼叫
//--------------------------------------------------------------------------------------------------------
void Start()
{
//依此賦值
ChangeValue = center;
ChangeValue2 = IterationNumber;
//找到當前的Shader檔案
CurShader = Shader.Find("3D/ScreenEdgeBlur1");
//判斷是否支持螢屏特效
if (!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}
}
//-------------------------------------【OnRenderImage()函式】------------------------------------
// 說明:此函式在當完成所有渲染圖片后被呼叫,用來渲染圖片后期效果
//--------------------------------------------------------------------------------------------------------
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
if (CurShader != null)
{
//申請兩塊降低解析度的RT 優化像素的采樣次數
//RenderTexture rt1 = RenderTexture.GetTemporary(sourceTexture.width / (int)IterationNumber, sourceTexture.height / (int)IterationNumber, 0, sourceTexture.format);
RenderTexture rt1 = RenderTexture.GetTemporary(sourceTexture.width, sourceTexture.height, 0, sourceTexture.format);
Graphics.Blit(sourceTexture, rt1);
//設定Shader中的外部變數
material.SetFloat("_IterationNumber", IterationNumber);
material.SetVector("_center", center);
//將進行過模糊操作的RT輸出出來用rt2存起來
Graphics.Blit(rt1, destTexture, material, 0);
RenderTexture.ReleaseTemporary(rt1);
}
//著色器實體為空,直接拷貝螢屏上的效果,此情況下是沒有實作螢屏特效的
else
{
//直接拷貝源紋理到目標渲染紋理
Graphics.Blit(sourceTexture, destTexture);
}
}
//-----------------------------------------【OnValidate()函式】--------------------------------------
// 說明:此函式在編輯器中該腳本的某個值發生了改變后被呼叫
//--------------------------------------------------------------------------------------------------------
void OnValidate()
{
//將編輯器中的值賦值回來,確保在編輯器中值的改變立刻讓結果生效
ChangeValue2 = IterationNumber;
ChangeValue = center;
}
//-----------------------------------------【OnDisable()函式】---------------------------------------
// 說明:當物件變為不可用或非激活狀態時此函式便被呼叫
//--------------------------------------------------------------------------------------------------------
void OnDisable()
{
if (CurMaterial)
{
DestroyImmediate(CurMaterial);
}
}
}
}
原圖

正常效果

降低解析度后的效果

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290752.html
標籤:其他
