UnityのHDRPでRadial Blur(放射状ブラー)のポストエフェクトを実装する方法についてまとめました。
Unity2020.3.22f1
High Definition RP 10.7.0
はじめに
本記事ではUnityのHDRPでRadial Blur(放射状ブラー)のポストエフェクトを実装する方法についてまとめます。
Radial Blurポストエフェクトの基礎知識については省略しますので、以下の記事を参照してください。
また、HDRPのカスタムポストエフェクトに関する基礎知識は以下の記事を参照してください。
シェーダを作成する
それではまずシェーダを作成します。
Shader "Hidden/Shader/RadialBlur" { HLSLINCLUDE #pragma target 4.5 #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/FXAA.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/RTUpscale.hlsl" struct Attributes { uint vertexID : SV_VertexID; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; float2 texcoord : TEXCOORD0; UNITY_VERTEX_OUTPUT_STEREO }; Varyings Vert(Attributes input) { Varyings output; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID); output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID); return output; } float _Intensity; float _SampleCount; TEXTURE2D_X(_InputTexture); float4 CustomPostProcess(Varyings input) : SV_Target { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); half3 col = 0; half2 symmetryUv = input.texcoord - 0.5; half distance = length(symmetryUv); half factor = _Intensity / _SampleCount * distance; for(int i = 0; i < _SampleCount; i++) { half uvOffset = 1 - factor * i; half2 uv = symmetryUv * uvOffset + 0.5; uint2 positionSS = uv * _ScreenSize.xy; col += LOAD_TEXTURE2D_X(_InputTexture, positionSS).rgb; } col /= _SampleCount; return float4(col, 1); } ENDHLSL SubShader { Pass { Name "RadialBlur" ZWrite Off ZTest Always Blend Off Cull Off HLSLPROGRAM #pragma fragment CustomPostProcess #pragma vertex Vert ENDHLSL } } Fallback Off }
HDRPの書き方に合わせて変えてますが処理自体は以下の記事と同じです。
Volumeスクリプトを作成する
次にVolumeスクリプトを作成します。
using System; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; [Serializable] [VolumeComponentMenu("Post-processing/Custom/RadialBlur")] public sealed class RadialBlur : CustomPostProcessVolumeComponent, IPostProcessComponent { private const string ShaderName = "Hidden/Shader/RadialBlur"; private static readonly int Intensity = Shader.PropertyToID("_Intensity"); private static readonly int SampleCount = Shader.PropertyToID("_SampleCount"); private static readonly int InputTexture = Shader.PropertyToID("_InputTexture"); public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f); public ClampedIntParameter sampleCount = new ClampedIntParameter(8, 4, 16); private Material _material; public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess; public bool IsActive() { return _material != null && intensity.value > 0f; } public override void Setup() { if (Shader.Find(ShaderName) != null) { _material = new Material(Shader.Find(ShaderName)); } else { Debug.LogError($"Unable to find shader '{ShaderName}'. Post Process Volume RadialBlur is unable to load."); } } public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination) { if (_material == null) { return; } _material.SetFloat(Intensity, intensity.value); _material.SetFloat(SampleCount, sampleCount.value); _material.SetTexture(InputTexture, source); HDUtils.DrawFullScreen(cmd, _material, destination); } public override void Cleanup() { CoreUtils.Destroy(_material); } }
こちらも特に難しいことはやっていません。
シーンに適用する
あとはこれを以下の記事のようにしてシーンに適用するだけです。
適用した結果は以下の通りとなりました。
アニメーションさせるとこんな感じです。
正常にRadial Blurが掛かっていることが確認できました。