Version: Unity 6.0 (6000.0)
言語 : 日本語
URP で HDR 出力を有効にする
URP でのスクリプタブルレンダーパスと HDR 出力のトラブルシューティング

URP に HDR 出力互換性のあるカスタムオーバーレイを実装する

このページでは、以下のことを行うスクリプタブルレンダラー機能の作成方法を説明します。

  • あるカメラの出力を別のカメラに合成する。
  • トーンマッピングを適用して、カスタムオーバーレイを HDR 出力の効果に合わせる。

これには、フレームの順序に応じてオーバーレイにトーンマッピングを適用するシェーダーが含まれます。

詳細については、スクリプタブルレンダラー機能の概要スクリプタブルレンダーパスの概要 を参照してください。

この例は、以下のセクションに分かれています。

必要条件

この例では、以下を前提としています。

  • Unity プロジェクトで、URP がアクティブなレンダーパイプラインとして使用されている。
  • プロジェクトは HDR レンダリング用に以下の設定で設定されている。
  • アクティブな URP アセットの Grading ModeHigh Dynamic Range に設定されている。
  • アクティブな URP アセットの HDR が有効にされている。
  • Project Settings で HDR Output が有効にされている。

シーンの設定

例を正しく動作させるには、まず以下の手順でサンプルのシーンを設定する必要があります。

  1. キューブゲームオブジェクトを作成し、その位置をシーンの原点 (X:0, Y:0, Z:0) に設定します。

  2. キューブがはっきり見えるように Main Camera を合わせます。

  3. 新しいカメラを作成し、Overlay Camera という名前を付けます。

  4. オーバーレイカメラを Main Camera の右側に置き、キューブがはっきり見えるように調整します。

  5. Inspector ウィンドウでオーバーレイカメラの Background Type プロパティを Solid Color に設定します。

  6. オーバーレイカメラの背景色を、RGBA 値を 0, 0, 0, 0 にして真っ黒に設定します。

  7. レンダーテクスチャを作成し、OverlayRenderTexture という名前を付けます。レンダーテクスチャを作成するには、Assets > Create > Rendering > Render Texture の順に選択します。

    ノート: HDR の精度を向上させるには、レンダーテクスチャ形式に符号付き Float 形式を使用します。これを行うには、レンダーテクスチャを選択してから、Inspector ウィンドウで Color Format_SFLOAT サフィックスを持つ形式に変更します。

  8. オーバーレイレンダーテクスチャをオーバーレイカメラの Output Texture プロパティに割り当てます。これを行うには、Inspector で Overlay Camera を開き、Output > Output Texture の順に移動し、アセットリストから OverlayRenderTexture を選択します。

  9. オーバーレイカメラ用の新しいユニバーサルレンダラーアセットを作成し、OverlayRenderer という名前を付けます。これを行うには、Assets > Create > Rendering > URP Universal Renderer の順に移動します。

  10. アクティブな URP アセットを選択してから、Inspector ウィンドウで Rendering > Renderer List > + の順に選択します。OverlayRenderer を選択します。これにより、オーバーレイレンダラーがレンダラーリストに追加されます。

  11. オーバーレイカメラを選択してから、Inspector ウィンドウで Rendering > Renderer の順に選択します。OverlayRenderer を選択します。これにより、オーバーレイカメラがオーバーレイレンダラーを使用するように設定されます。

これで、シーンでスクリプタブルレンダラー機能を使用してカスタムオーバーレイを作成する準備ができました。

カスタムオーバーレイレンダーパスの作成

HDR 出力と互換性のあるカスタムオーバーレイを作成するには、スクリプタブルレンダーパスを使用してオーバーレイを作成する必要があります。HDR 出力は、ポストプロセス中にメインカメラの出力にトーンマッピングを適用します。その結果、メインカメラとオーバーレイカメラの出力のトーンマッピングが、異なるものになります。このレンダーパスは、オーバーレイレイカメラの出力にトーンマッピングを適用するためのポストプロセス後に発生します。

この例のレンダーパスを作成するには、以下のステップに従います。

  1. C# スクリプトを作成し、CustomOverlayRenderPass という名前を付けます。

  2. このスクリプトで、Unity が CustomOverlayRenderPass クラスに挿入したコードを削除します。

  3. 以下の using ディレクティブを追加します。

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    using UnityEngine.Rendering.RenderGraphModule;
    
  4. ScriptableRenderPass クラスを継承し [SupportedOnRenderer(typeof(UniversalRendererData) --> 属性を持つ、新しい CustomOverlayRenderPass クラスを作成します。

    [SupportedOnRenderer(typeof(UniversalRendererData))] -->
    public class CustomOverlayRenderPass : ScriptableRenderPass
    {
      
    }
    
  5. 以下に示すように、プロパティ Material passMaterialRTHandle passOverlayTexture をレンダーパスに追加します。

    [SupportedOnRenderer(typeof(UniversalRendererData))] -->
    public class CustomOverlayRenderPass : ScriptableRenderPass
    {
        Material passMaterial;
        RTHandle overlayTextureHandle;
    }
    
  6. マテリアルをパラメーターとして受け取り、それを passMaterial に割り当てるコンストラクターメソッドを作成します。このメソッドで、レンダーパスのプロファイリングサンプラーも作成し、AfterRenderingPostProcessing イベントで実行されるように設定します。

    public CustomOverlayRenderPass(Material material)
    {
        passMaterial = material;
        profilingSampler = new ProfilingSampler(nameof(CustomOverlayRenderPass));
    
        renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }
    
  7. レンダーパスの Setup メソッドを追加します。このメソッドとパラメーターを使用して、以下に示すように、オーバーレイテクスチャから RTHandle を作成します。RTHandle を使用すると、RenderPass API はオーバーレイレンダーテクスチャと相互作用できます。

    public void Setup(Texture overlayTex)
    {
        if (overlayTextureHandle != overlayTex)
        {
            overlayTextureHandle?.Release();
            overlayTextureHandle = RTHandles.Alloc(overlayTex);
        }
    }
    
  8. レンダーパスが破棄されたときにオーバーレイテクスチャをリリースする、Dispose メソッドを実装します。

    public void Dispose()
    {
        overlayTextureHandle?.Release();
    }
    
  9. 以下に示すプロパティを含む 2 つの構造体を作成します。1 つは CopyData という名前、もう 1 つは PassData という名前にします。これらの構造体には、URP がレンダーパスを実装するために必要な主要なプロパティが保持されます。

    struct CopyData
    {
        public TextureHandle source;
    }
    
    struct PassData
    {
        public TextureHandle source;
        public TextureHandle overlayTexture;
        public TextureHandle internalLut;
        public Vector4 lutParams;
        public Material material;
    }
    
  10. 以下に示すように、RecordRenderGraph メソッドを追加します。

    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
    {
    
    }
    

RecordRenderGraph メソッドの実装

以下のステップで、CustomOverlayRenderPass クラスの RecordRenderGraph メソッド内にコードを追加します。

  1. フレームデータからポストプロセス、リソース、カメラのデータを取得します。

    UniversalPostProcessingData postProcessingData = frameData.Get<UniversalPostProcessingData>();
    UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
    UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
    
  2. リソースデータからアクティブなカラーテクスチャを取得します。

    TextureHandle activeCameraColor = resourceData.activeColorTexture;
    
  3. アクティブなカメラの色ターゲットを格納するテクスチャを作成します。

    RenderTextureDescriptor colorCopyDescriptor = cameraData.cameraTargetDescriptor;
    colorCopyDescriptor.depthBufferBits = (int) DepthBits.None;
    TextureHandle copiedColor = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorCopyDescriptor, "_CustomCameraColorCopy", false);
    
  4. アクティブなカメラの色ターゲットをテクスチャにコピーする RasterRenderPass を作成します。このコピーはブレンドの処理に使用されます。

    using (var builder = renderGraph.AddRasterRenderPass<CopyData>("Custom Overlay Render Pass - Copy Camera", out var passData))
    {
        passData.source = activeCameraColor;
        builder.UseTexture(passData.source, AccessFlags.Read);
        builder.SetRenderAttachment(copiedColor, 0, AccessFlags.WriteAll);
    
        builder.SetRenderFunc((CopyData data, RasterGraphContext context) =>
        {
            Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), 0.0f, false);
        });
    }
    
  5. カスタムマテリアルでオーバーレイテクスチャをアクティブなカメラの色ターゲットにコピーする、別の RasterRenderPass を作成します。これは、ガイドのこのセクションで追加する、残りのコードのコンテナです。

    using (var builder = renderGraph.AddRasterRenderPass<PassData>("Custom Overlay Render Pass - Blit Overlay", out var passData))
    {
        
    }
    
  6. 以下に示すように、レンダーパスがオーバーレイテクスチャを転送するために必要なプロパティを設定します。

    using (var builder = renderGraph.AddRasterRenderPass<PassData>("Custom Overlay Render Pass - Blit Overlay", out var passData))
    {
        passData.material = passMaterial;
    
        builder.SetRenderAttachment(activeCameraColor, 0, AccessFlags.Write);
    
        passData.source = copiedColor;
        builder.UseTexture(passData.source, AccessFlags.Read);
    }
    
  7. テクスチャをレンダーグラフシステムにインポートしてから、テクスチャを入力として設定します。

    passData.overlayTexture = renderGraph.ImportTexture(passOverlayTexture);
    builder.UseTexture(passData.overlayTexture, AccessFlags.Read);
    
  8. ポストプロセスと HDR カラーグレーディングを確認します。HDR 出力 の設定が正しい場合は、HDR が入力として使用する内部色の LUT テクスチャを設定し、そのパラメーターをシェーダーに渡します。

    if (postProcessingData.gradingMode == ColorGradingMode.HighDynamicRange && cameraData.postProcessEnabled)
    {
        passData.internalLut = resourceData.internalColorLut;
        builder.UseTexture(passData.internalLut, AccessFlags.Read);
    
        int lutHeight = postProcessingData.lutSize;
        int lutWidth = lutHeight * lutHeight;
    
        float postExposure = 1.0f;
        ColorAdjustments colorAdjustments = VolumeManager.instance.stack.GetComponent<ColorAdjustments>();
        if (colorAdjustments != null)
        {
            postExposure = Mathf.Pow(2.0f, colorAdjustments.postExposure.value);
        }
    
        passData.lutParams = new Vector4(1f / lutWidth, 1f / lutHeight, lutHeight - 1f, postExposure);
    }
    

    ノート: ポストプロセスが無効な場合、HDR の色変換はこのレンダーパスの後に適用され、カメラ出力に期待される色空間はデフォルトの Rec709 になります。この例のコードは、ここで if ステートメントを使用して、このレンダーパスが HDR が適用される前にオーバーレイカメラの出力を変更しないようにしています。

  9. シェーダーにキーワードを設定してトーンマッピングを有効にし、オーバーレイテクスチャをアクティブなカメラの色ターゲットに転送するためのコマンドを追加します。

    builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
    {
        data.material.SetTexture("_OverlayTexture", data.overlayTexture);
    
        bool tonemappingActive = data.internalLut.IsValid();
        CoreUtils.SetKeyword(data.material, "TONEMAPPING", tonemappingActive);
        if (tonemappingActive)
        {
            data.material.SetTexture("_InternalLut", data.internalLut);
            data.material.SetVector("_InternalLut_Params", data.lutParams);
        }
            
        Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0);
    });
    

これで CustomOverlayRenderPass スクリプトは完成し、スクリプタブルレンダラー機能をレンダラーに追加できるようになりました。

このセクションの完全なコードについては、カスタムオーバーレイレンダーパスのコード を参照してください。

カスタムオーバーレイスクリプタブルレンダラー機能の作成

CustomOverlayRenderPass をレンダラーに追加するには、以下のステップでスクリプタブルレンダラー機能を作成する必要があります。

  1. C# スクリプトを作成し、CustomOverlayRendererFeature という名前を付けます。

  2. このスクリプトで、Unity が CustomOverlayRendererFeature クラスに挿入したコードを削除します。

  3. 以下の using ディレクティブを追加します。

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
  4. ScriptableRendererFeature クラスを継承する新しい CustomOverlayRendererFeature クラスを設定します。

    public class CustomOverlayRendererFeature : ScriptableRendererFeature
    {
      
    }
    
  5. レンダーパスに必要なアセットとデータを格納するために、以下のプロパティを追加します。

    public class CustomOverlayRendererFeature : ScriptableRendererFeature
    {
        public Shader hdrShader;
        public RenderTexture passOverlayTexture;
    
        Material passMaterial;
    
        CustomOverlayRenderPass overlayRenderPass = null;
    }
    
  6. AddRenderPasses メソッドを作成し、ゲームビューとカメラスタックの最後のカメラにのみオーバーレイを適用するために使用します。

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType != CameraType.Game || !renderingData.cameraData.resolveFinalTarget)
            return;
    }
    
  7. if ステートメントの後で、オーバーレイテクスチャをオーバーレイレンダーパスに渡し、レンダーパスをキューに入れます。

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType != CameraType.Game || !renderingData.cameraData.resolveFinalTarget)
            return;
    
        overlayRenderPass.Setup(passOverlayTexture);
    
        renderer.EnqueuePass(overlayRenderPass);
    }
    
  8. Create メソッドを追加し、hdrShader を使用する新しいマテリアルで CustomOverlayRenderPass のインスタンスを作成します。

    public override void Create()
    {
        passMaterial = CoreUtils.CreateEngineMaterial(hdrShader);
    
        overlayRenderPass = new CustomOverlayRenderPass(passMaterial);
    }
    
  9. レンダーパスの適用後にレンダラー機能が作成するリソースをリリースする、Dispose メソッドを実装します。

    protected override void Dispose(bool disposing)
    {
        CoreUtils.Destroy(passMaterial);
        overlayRenderPass.Dispose();
    }
    

このセクションの完全なコードについては、カスタムオーバーレイスクリプタブルレンダラー機能のコード を参照してください。

カスタムオーバーレイシェーダーの作成

CustomOverlayRendererFeature が作成するマテリアルには、オーバーレイと HDR 出力の変更を処理するカスタムシェーダーが必要です。以下のステップで、これに対応するシェーダーの作成方法を示します。

  1. 新しいシェーダーを作成し、CustomOverlayBlit という名前を付けます。

  2. Unity が自動的に生成するシェーダーコードを削除し、以下に示すように、シェーダーのアウトラインを設定します。

    Shader "Custom/CustomOverlayBlit"
    {
        SubShader
        {
            Tags{ "RenderPipeline" = "UniversalPipeline" }
    
            Pass
            {
                ZWrite Off ZTest Always Blend Off Cull Off
    
                HLSLPROGRAM
                    #pragma target 2.0
                    #pragma editor_sync_compilation
                    #pragma vertex Vert
                    #pragma fragment Frag
                    #pragma multi_compile_local_fragment _ TONEMAPPING
    
                    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                    #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
                    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
                    
                    TEXTURE2D(_InternalLut);
                    TEXTURE2D_X(_OverlayTexture);
    
                    float4 _InternalLut_Params;
    
                    #define LutParams _InternalLut_Params.xyz
                    #define PostExposure _InternalLut_Params.w
    
                ENDHLSL
            }
        }
    }
    
  3. 名前が ApplyTonemapping で戻り値の型が half3 のメソッドを作成します。このメソッドにはパラメーター、half3 inputTEXTURE2D_PARAM(lutTex, lutSampler)float3 lutParamsfloat exposure を持たせてください。

  4. ApplyTonemapping メソッドで、inputexposure 値を乗算してから、変更した inputsaturate に渡します。

    half3 ApplyTonemapping(half3 input, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, float exposure)
    {
        input *= exposure;
        float3 inputLutSpace = saturate(LinearToLogC(input));
    }
    
  5. ApplyLut2D でトーンマッピングの変更を適用し、結果を返します。

    half3 ApplyTonemapping(half3 input, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, float exposure)
    {
        input *= exposure;
        float3 inputLutSpace = saturate(LinearToLogC(input));
        return ApplyLut2D(TEXTURE2D_ARGS(lutTex, lutSampler), inputLutSpace, lutParams);
    }
    
  6. 以下に示すように、標準の Frag メソッドを作成します。このメソッドを HLSLPROGRAM 内、ただし ApplyTonemapping メソッドの後に配置します。

    half4 Frag(Varyings input) : SV_Target
    {
    
    }
    
  7. Frag メソッドで、元のカメラの色とオーバーレイの色を取得します。

    half4 Frag(Varyings input) : SV_Target
    {
        half4 color = FragBlit(input, sampler_LinearClamp);
    
        half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord);
    }
    
  8. シェーダーがトーンマッピングを適用するかどうかを確認する if ステートメントを作成します。シェーダーがトーンマッピングを適用する必要がある場合は、ApplyTonemapping メソッドを使用してオーバーレイに適用します。

    half4 Frag(Varyings input) : SV_Target
    {
        half4 color = FragBlit(input, sampler_LinearClamp);
    
        half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord);
    
        #if TONEMAPPING
        overlay.rgb = ApplyTonemapping(overlay.rgb, TEXTURE2D_ARGS(_InternalLut, sampler_LinearClamp), LutParams, PostExposure);
        #endif
    }
    
  9. オーバーレイを元のカメラの色とブレンドし、結果を返します。

    half4 Frag(Varyings input) : SV_Target
    {
        half4 color = FragBlit(input, sampler_LinearClamp);
    
        half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord);
    
        #if TONEMAPPING
        overlay.rgb = ApplyTonemapping(overlay.rgb, TEXTURE2D_ARGS(_InternalLut, sampler_LinearClamp), LutParams, PostExposure);
        #endif
    
        color.rgb = color.rgb * (1.0 - overlay.a) + overlay.rgb * overlay.a;
        return color;
    }
    

これでシェーダーは完成し、CustomOverlayRenderPass スクリプトと CustomOverlayRendererFeature スクリプトで使用できるようになりました。

このセクションの完全なコードを確認するには、カスタムオーバーレイシェーダーのコード を参照してください。

カスタムオーバーレイの仕上げ

カスタムオーバーレイを仕上げるには、作成したスクリプトを設定し、その効果をシーン内のレンダラーに適用する必要があります。以下のステップは、その方法を示しています。

  1. アクティブな URP アセットが使用するメインレンダラーを検索して選択します。
  2. Inspector ウィンドウで、Add Renderer Feature > Custom Overlay Renderer Feature の順に選択して、CustomOverlayRendererFeature スクリプトを追加します。
  3. CustomOverlayBlit シェーダーをカスタムオーバーレイスクリプタブルレンダラー機能の Shader プロパティに割り当てます。
  4. OverlayRenderTexture をカスタムオーバーレイスクリプタブルレンダラー機能の Overlay Texture プロパティに割り当てます。

これでカスタムオーバーレイは完成し、再生モードでメインカメラの出力の上に表示されます。このオーバーレイは、メインカメラの出力と同じ方法でトーンマップされ、目に見える違いはありません。これは以下のスクリーンショットのようになります。

ゲームビューの中央にあるキューブと、オーバーレイとして別の角度からのキューブ。HDR 出力に合わせてトーンマップされている
ゲームビューの中央にあるキューブと、オーバーレイとして別の角度からのキューブ。HDR 出力に合わせてトーンマッピされています。

ノート: 最終的な結果は、オーバーレイカメラの配置によって異なる場合があります。

完全コードサンプル

カスタムオーバーレイレンダーパスのコード

以下は、この例のスクリプタブルレンダーパスの完全なコードサンプルです。

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;

[SupportedOnRenderer(typeof(UniversalRendererData))] -->
public class CustomOverlayRenderPass : ScriptableRenderPass
{
    Material passMaterial;
    RTHandle overlayTextureHandle;

    public CustomOverlayRenderPass(Material material)
    {
        passMaterial = material;
        profilingSampler = new ProfilingSampler(nameof(CustomOverlayRenderPass));

        // The render pass is executed after post processing, so the main camera target has been tonemapped but not the overlay texture
        renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }

    public void Setup(Texture overlayTex)
    {
        //Create an RTHandle from the overlay texture, to import it into the render graph system
        if (overlayTextureHandle != overlayTex)
        {
            overlayTextureHandle?.Release();
            overlayTextureHandle = RTHandles.Alloc(overlayTex);
        }
    }

    public void Dispose()
    {
        overlayTextureHandle?.Release();
    }

    class CopyData
    {
        public TextureHandle source;
    }

    class PassData
    {
        public TextureHandle source;
        public TextureHandle overlayTexture;
        public TextureHandle internalLut;
        public Vector4 lutParams;
        public Material material;
    }
    
    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
    {
        UniversalPostProcessingData postProcessingData = frameData.Get<UniversalPostProcessingData>();
        UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
        UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();

        TextureHandle activeCameraColor = resourceData.activeColorTexture;

        // Create a texture to copy the active camera color target into
        RenderTextureDescriptor colorCopyDescriptor = cameraData.cameraTargetDescriptor;
        colorCopyDescriptor.depthBufferBits = (int) DepthBits.None;
        TextureHandle copiedColor = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorCopyDescriptor, "_CustomCameraColorCopy", false);

        // Copy the active camera color target into the texture
        using (var builder = renderGraph.AddRasterRenderPass<CopyData>("Custom Overlay Render Pass - Copy Camera", out var passData))
        {
            passData.source = activeCameraColor;
            builder.UseTexture(passData.source, AccessFlags.Read);
            builder.SetRenderAttachment(copiedColor, 0, AccessFlags.WriteAll);

            builder.SetRenderFunc((CopyData data, RasterGraphContext context) =>
            {
                Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), 0.0f, false);
            });
        }

        using (var builder = renderGraph.AddRasterRenderPass<PassData>("Custom Overlay Render Pass - Blit Overlay", out var passData))
        {
            passData.material = passMaterial;

            builder.SetRenderAttachment(activeCameraColor, 0, AccessFlags.Write);

            passData.source = copiedColor;
            builder.UseTexture(passData.source, AccessFlags.Read);

            // Import the overlay texture that will be copied onto the camera color, and set it as an input
            passData.overlayTexture = renderGraph.ImportTexture(overlayTextureHandle);
            builder.UseTexture(passData.overlayTexture, AccessFlags.Read);

            // If post-processing is enabled on the main camera, apply the tonemapping to the overlay texture as well
            // If post processing is disabled, the HDR color conversion will be applied after this render pass and the expected colorspace for the cameras output is the default Rec709
            if (postProcessingData.gradingMode == ColorGradingMode.HighDynamicRange && cameraData.postProcessEnabled)
            {
                // Import the internal color LUT texture used for HDR color grading and tonemapping
                // This includes any HDR color conversion URP needs for the display, so the output of the camera is in the display's color gamut
                passData.internalLut = resourceData.internalColorLut;
                builder.UseTexture(passData.internalLut, AccessFlags.Read);

                // Pass LUT parameters to the shader
                int lutHeight = postProcessingData.lutSize;
                int lutWidth = lutHeight * lutHeight;

                float postExposure = 1.0f;
                ColorAdjustments colorAdjustments = VolumeManager.instance.stack.GetComponent<ColorAdjustments>();
                if (colorAdjustments != null)
                {
                    postExposure = Mathf.Pow(2.0f, colorAdjustments.postExposure.value);
                }

                passData.lutParams = new Vector4(1f / lutWidth, 1f / lutHeight, lutHeight - 1f, postExposure);
            }

            builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
            {
                // Pass parameters to the shader
                data.material.SetTexture("_OverlayTexture", data.overlayTexture);

                // Set a keyword on the shader to enable tonemapping
                bool tonemappingActive = data.internalLut.IsValid();
                CoreUtils.SetKeyword(data.material, "TONEMAPPING", tonemappingActive);
                if (tonemappingActive)
                {
                    data.material.SetTexture("_InternalLut", data.internalLut);
                    data.material.SetVector("_InternalLut_Params", data.lutParams);
                }
                
                // Blit the overlay texture onto the camera color
                Blitter.BlitTexture(context.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0);
            });
        }
    }
}

カスタムオーバーレイスクリプタブルレンダラー機能のコード

以下は、この例のスクリプタブルレンダラー機能の完全なコードサンプルです。

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class CustomOverlayRendererFeature : ScriptableRendererFeature
{
    public Shader hdrShader;
    public RenderTexture passOverlayTexture;

    Material passMaterial;

    CustomOverlayRenderPass overlayRenderPass = null;

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        // Render the overlay onto the main camera during Game view rendering only, for the last camera in the camera stack
        if (renderingData.cameraData.cameraType != CameraType.Game || !renderingData.cameraData.resolveFinalTarget)
            return;

        // Pass the overlay texture at runtime in case it changes
        overlayRenderPass.Setup(passOverlayTexture);

        // Enqueue the render pass to be executed
        renderer.EnqueuePass(overlayRenderPass);
    }

    public override void Create()
    {
        // Create a blit material from the given shader
        passMaterial = CoreUtils.CreateEngineMaterial(hdrShader);

        // Create the render pass
        overlayRenderPass = new CustomOverlayRenderPass(passMaterial);
    }

    protected override void Dispose(bool disposing)
    {
        // Destroy the render pass resources
        CoreUtils.Destroy(passMaterial);
        overlayRenderPass.Dispose();
    }
}

カスタムオーバーレイシェーダーのコード

以下は、この例のシェーダーの完全なコードサンプルです。

Shader "Custom/CustomOverlayBlit"
{
    SubShader
    {
        Tags{ "RenderPipeline" = "UniversalPipeline" }

        Pass
        {
            ZWrite Off ZTest Always Blend Off Cull Off

            HLSLPROGRAM
                #pragma target 2.0
                #pragma editor_sync_compilation
                #pragma vertex Vert
                #pragma fragment Frag
                #pragma multi_compile_local_fragment _ TONEMAPPING

                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
                
                TEXTURE2D(_InternalLut);
                TEXTURE2D_X(_OverlayTexture);

                float4 _InternalLut_Params;

                #define LutParams _InternalLut_Params.xyz
                #define PostExposure _InternalLut_Params.w

                half3 ApplyTonemapping(half3 input, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, float exposure)
                {
                    input *= exposure;
                    float3 inputLutSpace = saturate(LinearToLogC(input)); // LUT space is in LogC
                    return ApplyLut2D(TEXTURE2D_ARGS(lutTex, lutSampler), inputLutSpace, lutParams);
                }

                half4 Frag(Varyings input) : SV_Target
                {
                    // Get the original camera color
                    half4 color = FragBlit(input, sampler_LinearClamp);

                    // Get the overlay color
                    half4 overlay = SAMPLE_TEXTURE2D_X(_OverlayTexture, sampler_LinearClamp, input.texcoord);

                    // Tonemap the overlay
                    #if TONEMAPPING
                    overlay.rgb = ApplyTonemapping(overlay.rgb, TEXTURE2D_ARGS(_InternalLut, sampler_LinearClamp), LutParams, PostExposure);
                    #endif

                    // Blend overlay and color
                    color.rgb = color.rgb * (1.0 - overlay.a) + overlay.rgb * overlay.a;
                    return color;
                }

            ENDHLSL
        }
    }
}
URP で HDR 出力を有効にする
URP でのスクリプタブルレンダーパスと HDR 出力のトラブルシューティング