【Unity】【シェーダ】回転ブラーのポストエフェクトを実装する

Unityのシェーダで回転ブラーのポストエフェクトを実装する方法です。

Unity2019.2.11

はじめに

この記事ではUnityのシェーダで回転ブラーのポストエフェクトを実装する方法をまとめます。
Unityでポストエフェクトを掛ける基本的な方法については以下の記事にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

シェーダ

早速ですが、まずシェーダ全文を掲載します。

Shader "Example"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
        _SampleCount ("Sample Count", int) = 5
        _Intensity ("Intensity", float) = 0.05
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

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

            sampler2D _MainTex;
            int _SampleCount;
            float _Intensity;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                half angleRad = _Intensity / _SampleCount;
                half3 rgb = tex2D(_MainTex, i.uv).rgb;
                
                for(int j = 1; j < _SampleCount; j++)
                {
                    half sign = j % 2 * 2 - 1;
                    half angle = angleRad * j * sign;
                    half angleCos = cos(angle);
                    half angleSin = sin(angle);
                    half2x2 rotateMatrix = half2x2(angleCos, -angleSin, angleSin, angleCos);
                    float2 uv = mul(i.uv - 0.5, rotateMatrix) + 0.5;
                    rgb += tex2D(_MainTex, uv).rgb;
                }
                rgb /= _SampleCount;
                return fixed4(rgb, 1);
            }
            ENDCG
        }
    }
}

内容としては、下記の記事の方法で入力のテクスチャを回転させながらサンプリングしています。

light11.hatenadiary.com

レンダリング結果

さてこれをポストエフェクトとしてレンダリングします。
ポストエフェクトを掛けるためのスクリプトは以下のように書きます。

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField]
    private Material _material;
    [SerializeField, Range(1, 20)]
    private int _sampleCount = 5;
    [SerializeField, Range(0.0f, 1.0f)]
    private float _intensity = 0.05f;

    private void OnRenderImage(RenderTexture source, RenderTexture dest)
    {
        _material.SetFloat("_SampleCount", _sampleCount);
        _material.SetFloat("_Intensity", _intensity);
        Graphics.Blit(source, dest, _material);
    }
}

これをカメラにアタッチして実行すると以下の結果が得られます。

f:id:halya_11:20191206011950p:plain
適用前

f:id:halya_11:20191206012047p:plain
軽くかけた状態

f:id:halya_11:20191206012034p:plain
強くかけた状態

関連

light11.hatenadiary.com