UnityのHDRPでカスタムポストエフェクトを実装する方法についてまとめました。
Unity2020.3.22f1
High Definition RP 10.7.0
はじめに
本記事ではUnityのHigh Definition RP (HDRP)でカスタムポストエフェクトを作成する方法についてまとめます。
HDRPおよびポストエフェクトの基本的な使い方については本記事では扱わないので、必要に応じてマニュアルを参照してください。
シェーダを作成する
それではまずシェーダから作成します。
HDRPではポストエフェクト用のシェーダのテンプレートが用意されているので、
Assets > Create > Shader > HD Render Pipeline > Post Process
からシェーダファイルを作成します。
ファイル名はExampleにしておきます。
これをベースにエフェクトを作成します。
今回は簡単に画面を赤くするエフェクトを作成します。
Shader "Hidden/Shader/Example" { 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; TEXTURE2D_X(_InputTexture); float4 CustomPostProcess(Varyings input) : SV_Target { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); uint2 positionSS = input.texcoord * _ScreenSize.xy; float3 outColor = LOAD_TEXTURE2D_X(_InputTexture, positionSS).xyz; // ここだけ追加しました outColor *= lerp(float3(1, 1, 1), float3(1, 0, 0), _Intensity); return float4(outColor, 1); } ENDHLSL SubShader { Pass { Name "Example" ZWrite Off ZTest Always Blend Off Cull Off HLSLPROGRAM #pragma fragment CustomPostProcess #pragma vertex Vert ENDHLSL } } Fallback Off }
コメントをつけた一行だけテンプレートから変えました。
スクリプトを作成する
さて次に必要なスクリプトを作成します。
こちらもテンプレートが用意されているので、Assets > Create > Rendering > C# Post Process Volume
から作成します。
こちらもシェーダと同様に名前はExampleにしておきます。
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using System; [Serializable, VolumeComponentMenu("Post-processing/Custom/Example")] public sealed class Example : CustomPostProcessVolumeComponent, IPostProcessComponent { // Volumeコンポーネントから設定してシェーダに渡すパラメータ // このようにVolumeParameterの派生クラスを使用する [Tooltip("Controls the intensity of the effect.")] public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f); Material m_Material; // 無駄に処理が走らないように有効状態を返す public bool IsActive() => m_Material != null && intensity.value > 0f; // このポストエフェクトをかけるタイミング public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess; // シェーダ名 const string kShaderName = "Hidden/Shader/Example"; public override void Setup() { if (Shader.Find(kShaderName) != null) m_Material = new Material(Shader.Find(kShaderName)); else Debug.LogError($"Unable to find shader '{kShaderName}'. Post Process Volume Example is unable to load."); } public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination) { if (m_Material == null) return; m_Material.SetFloat("_Intensity", intensity.value); m_Material.SetTexture("_InputTexture", source); HDUtils.DrawFullScreen(cmd, m_Material, destination); } public override void Cleanup() { CoreUtils.Destroy(m_Material); } }
今回は中身は特に変える必要はありません。
説明のためにコメントだけ記述しました。
シーンに適用する
最後にこのエフェクトをシーンに適用していきます。
まずProject Settings > HDRP Default Settings > Custom Post Process Orders
の.
After Post Process
の+ボタンを押下して今回作ったExample
エフェクトを追加します。
次にシーン上にPost Processingをセットアップし、Volume
コンポーネントのAdd Override
ボタンから、
Post-processing > Custom > Example
を選択します。
Intensityにチェックを入れてスライダーの値を大きくすると、以下のようにポストエフェクトが適用されることを確認できます。