LoginSignup
26
14

More than 3 years have passed since last update.

HDRPでポストエフェクトやる

Last updated at Posted at 2019-09-03

<追記 2019-10-05>
HDRPがカスタムポストエフェクト対応したそうです。この記事の3日後にマージされとる……😂
https://github.com/Unity-Technologies/ScriptableRenderPipeline/pull/4484
</追記ここまで>

UnityのHDRPを使うと高品質なレンダリングが可能になりますが、まだユーザーがポストエフェクトを作成できません。
Unity公式フォーラムでは「2019.3で対応するつもりだよ~」とアナウンスされていますが、今のところ具体的なスケジュールはまだ未定のようです。
https://forum.unity.com/threads/custom-post-processing-effects-with-new-hdrp-workflow.689317/

昨日↑のスレを見返した所、Another Angle Gamesのnehvaleem氏がHDRPをforkしてポストエフェクトを自作するチュートリアルを投稿してくれていました!
https://medium.com/another-angle/custom-post-processing-using-hdrp-in-unity-2019-x-60302a2fa1e0

この記事では、↑のチュートリアルに沿って解説します。
↑のチュートリアルではシェーダー周りはノータッチだったり色々ハマりどころもあったので、その辺もカバーしていきます。

前提

  • Unityのバージョン: 2019.2
  • HDRPのバージョン: 6.9.1

手順

  • HDRPをfork
  • HDRPプロジェクトを新規作成
  • forkしたHDRPをプロジェクトに突っ込む
  • 自作PostProcessComponentを作る
  • 自作PostProcessComponentをロードする
  • PostProcessingSystemをいじる

HDRPをfork

HDRPはScriptableRenderPipelineの中にあるので、まずはこちらをcloneします。
けっこう時間かかるんで気長に待ちましょう。
https://github.com/Unity-Technologies/ScriptableRenderPipeline

git clone https://github.com/Unity-Technologies/ScriptableRenderPipeline
cd ScriptableRenderPipeline

HDRPは、Unityのバージョンに合わせて異なるバージョンを使う必要があります。
バージョン毎にタグが切られてるのでcheckoutしましょう。
2019.2の場合は6.9.1です。

git checkout 6.9.1

HDRPプロジェクトを新規作成

次に、Unityで新規プロジェクトを作成します。
プロジェクト作成ダイアログで HDRP を選択してください。
image.png

HDRPのサンプルシーンが作成されます。きれいですね~

image.png

従来のUnityではPost Processing Stackをインポートしてポストエフェクトをかけていましたが、HDRPではPost Processing Stackが最初から組み込まれています。
Hierarchyビューで Scene Post-processを選択してインスペクターを見ると、既にいくつかポストエフェクトが設定されていることがわかります。

image.png

forkしたHDRPをプロジェクトに突っ込む

まず、標準で入っているHDRPを削除します。
Window > Package ManagerからHigh Definition RPを選択し、Removeをクリック。
image.png

次に、先程cloneしたHDRPをインストールします。
Package Managerの+ボタンからAdd package from disk...をクリック。

image.png

先程cloneしたレポジトリから、 ScriptableRenderPipeline/com.unity.render-pipelines.high-definition/package.json を選択し、開く をクリックすると、HDRPのインストールが始まります。
image.png

自作PostProcessComponentを作る

それでは、ついにポストエフェクトを作っていきます。

HDRPのポストエフェクトは、IPostProcessComponentを実装したクラスとシェーダーの2ファイルで構成されています。

  • IPostProcessComponent: エフェクトのパラメータ等を管理
  • シェーダー: エフェクト処理

まずIPostProcessComponentのクラスを作りましょう。
HDRPレポジトリの Runtime/PostProcessing/ComponentsGlitch.cs を作成します。

using System;
using UnityEngine.Rendering;

namespace UnityEngine.Experimental.Rendering.HDPipeline
{
    [Serializable, VolumeComponentMenu("Post-processing/Glitch")]
    public sealed class Glitch : VolumeComponent, IPostProcessComponent
    {
        // BoolParameterを使うと、Inspector上ではチェックボックスが表示される
        public BoolParameter isEnabled = new BoolParameter(false);

        // ColorParameterを使うと、Inspector上ではカラーピッカーが表示される
        [Tooltip("Overlay color for glitch")]
        public ColorParameter overlayColor = new ColorParameter(new Color(0,0,0,0), false, true, true);

        // ClampedFloatParameterを使うと、Inspector上ではスライダーが表示される
        [Tooltip("Intensity of glitch")]
        public ClampedFloatParameter intensity = new ClampedFloatParameter(0.03f, 0f, 0.2f);

        // 実装必須
        public bool IsActive()
        {
            return isEnabled.value;
        }
    }
}

次に、HDRPレポジトリの Runtime/PostProcessing/ShadersGlitch.shader を作成します。

Shader "Hidden/Glitch"
{
    SubShader
    {
        Tags{ "RenderPipeline" = "HDRenderPipeline" }

        Pass
        {
            ZWrite On ZTest Always Blend Off Cull Off

            HLSLPROGRAM
                #pragma target 4.5
                #pragma only_renderers d3d11 ps4 xboxone vulkan metal switch

                #pragma vertex Vert
                #pragma fragment Frag

                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
                #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"

                TEXTURE2D_X(_InputTexture);

                float4 _OverlayColor;
                float _Intensity;

                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;
                }

                float4 Frag(Varyings input) : SV_Target0
                {
                    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

                    float2 uv = input.texcoord.xy;
                    float time = _Time.y;

                    // ここにエフェクトを書く。
                    // 今回は適当にグリッチしてる
                    float4 outColor = LOAD_TEXTURE2D_X(_InputTexture, uv * _ScreenSize.xy);
                    float n = sin(floor(uv.y * 23. + time * 3.)) * sin(floor(uv.y * 17. + time * 39.));
                    if (frac(n * 170.) < 0.1) {
                        uv.x = frac(uv.x + n * _Intensity);
                        outColor = LOAD_TEXTURE2D_X(_InputTexture, uv * _ScreenSize.xy);
                        outColor += _OverlayColor * _OverlayColor.a;
                    }

                    return outColor;
                }

            ENDHLSL
        }
    }
    Fallback Off
}

自作PostProcessComponentをロードする

Runtime/RenderPipeline/RenderPipelineResources.cs を開きます。
GetAllComputeShadersの上あたりに、以下のコードを追加します。

[Reload("Runtime/PostProcessing/Shaders/Glitch.shader")]
public Shader GlitchPS;

PostProcessingSystemをいじる

最後にPostProcessingSystemを編集し、レンダリングの終段でポストエフェクトがちゃんと実行されるようにします。
Runtime/PostProcessing/PostProcessingSystem.cs を開き、以下のプロパティを追加してください。

Material m_GlitchMaterial;
Glitch m_Glitch;

次に、コンストラクタにmaterialの初期化処理を追加します。

// さっき作ったシェーダーからマテリアルを作成
m_GlitchMaterial = CoreUtils.CreateEngineMaterial(m_Resources.shaders.GlitchPS);

ついでに Cleanup() 内でちゃんと後処理してあげましょう。

CoreUtils.Destroy(m_GlitchMaterial);
m_GlitchMaterial = null;

m_Glitchの初期化はBeginFrame()で行います。

public void BeginFrame(CommandBuffer cmd, HDCamera camera)
{
    // 中略

    var stack = VolumeManager.instance.stack;
    // 中略
    m_Glitch = stack.GetComponent<Glitch>(); // この行を追加
}

いよいよRender()を編集します。
460行目あたりに // TODO: User effects go here というコメントがあるので、その下に以下のコードをコピペしてください。

if (m_PostProcessEnabled)
{
    if (m_Glitch.IsActive())
    {

        var destination = m_Pool.Get(Vector2.one, k_ColorFormat);
        DoGlitchPass(cmd, camera, source, destination);
        PoolSource(ref source, destination);
    }
}

DoGlitchPassの実装を追加します。
DoFinalPassの上あたりに以下のコードをコピペしてください。

#region Glitch Pass
void DoGlitchPass(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination)
{
    // マテリアルにパラメーターを渡す
    m_GlitchMaterial.SetTexture(HDShaderIDs._InputTexture, source);
    m_GlitchMaterial.SetVector(Shader.PropertyToID("_OverlayColor"), m_Glitch.overlayColor.value);
    m_GlitchMaterial.SetFloat(Shader.PropertyToID("_Intensity"), m_Glitch.intensity.value);

    // destinationに描画
    HDUtils.DrawFullScreen(cmd, m_GlitchMaterial, destination);
}
#endregion

これでコードの編集は終了です~

使ってみよう

Scene Post-processのインスペクターで Add overrideをクリックし、Post-processing > Glitchを選択します。

image.png

パラメーターをポチポチすると動くはず!

ワーイ

26
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
14