Version: Unity 6.0 (6000.0)
言語 : 日本語
URP で前のフレームのデータを取得する
URP のフレームバッファフェッチによる現在のフレームバッファの取得

カメラ履歴にテクスチャを追加する

独自のテクスチャをカメラ履歴に追加し、後続のフレームでデータを読み込むには、フレーム間でテクスチャを格納するカメラ履歴タイプを作成します。

カメラ履歴タイプの作成

以下の手順に従ってください。

  1. CameraHistoryItem を継承するクラスを作成します。例:

    public class ExampleHistoryType : CameraHistoryItem {
        ...
    }
    
  2. クラスに、カメラ履歴システムの ID を追加します。例:

        private int uniqueId;
    

    ID は、現在のフレームと前のフレームを含む、1 つのテクスチャの完全な履歴を表します。

    また、フレーム間で保存する必要があるテクスチャ記述子など、必要な他のデータを追加することもできます。

  3. OnCreate メソッドをオーバーライドします。メソッドで、親クラスの OnCreate メソッドを呼び出し、一意の ID を生成します。例:

    public override void OnCreate(BufferedRTHandleSystem owner, uint typeId)
    {
        // Call the OnCreate method of the parent class
        base.OnCreate(owner, typeId);
    
        // Generate the unique id
        uniqueId = MakeId(0);
    }
    
  4. 現在のテクスチャと前のテクスチャのパブリックプロパティを作成し、レンダーパスがそれらにアクセスできるようにします。例:

    public RTHandle currentTexture => GetCurrentFrameRT(uniqueId);
    public RTHandle previousTexture => GetPreviousFrameRT(uniqueId);
    
  5. テクスチャ用のメモリを割り当てます。例:

    // Allocate 2 textures using a texture descriptor, assign them to the uniqueId, and give them a name.
    AllocHistoryFrameRT(uniqueId, 2, ref textureDescriptor, "ExampleHistoryTexture");
    

また、レンダーパスが異なるサイズや形式のテクスチャを書き込む場合は、フレームごとにメモリの再割り当てが必要になる場合もあります。

テクスチャへの書き込み

作成したテクスチャに書き込むには、以下の手順に従います。

  1. ScriptableRenderPass クラスのテクスチャへのアクセスをリクエストするには、カメラ履歴タイプで RequestAccess API を使用します。例:

    cameraData.historyManager.RequestAccess<ExampleHistoryType>();
    
  2. 書き込みのために現在のフレームのテクスチャを取得し、レンダーグラフシステムが使用できるハンドルに変換します。例:

    // Get the textures 
    ExampleHistoryType history = cameraData.historyManager.GetHistoryForWrite<ExampleHistoryType>();
    
    // Get the texture for the current frame, using the unique id
    RTHandle historyTexture = history?.currentTexture(theUniqueid);
    
    // Convert the texture into a handle the render graph system can use
    historyTexture = renderGraph.ImportTexture(historyTexture);
    

その後、レンダーパス内のテクスチャに書き込むことができます。詳細については、テクスチャの使用を参照してください。

テクスチャの読み込み

テクスチャから読み込むには、作成したカメラ履歴タイプで RequestAccess API を使用します。

テクスチャから読み込む前に、テクスチャに書き込む必要があります。

詳細は、前のフレームからデータを取得するを参照してください。

以下は、カメラ履歴タイプの例です。

public class ExampleHistoryType : CameraHistoryItem
{
    private int m_Id;
    
    // Add a descriptor for the size and format of the texture.
    private RenderTextureDescriptor m_Descriptor;

    // Add a hash key to track changes to the descriptor.
    private Hash128 m_DescKey;
    
    public override void OnCreate(BufferedRTHandleSystem owner, uint typeId)
    {
        base.OnCreate(owner, typeId);
        m_Id = MakeId(0);
    }
    
    public RTHandle currentTexture => return GetCurrentFrameRT(m_Id);
    public RTHandle previousTexture => return GetPreviousFrameRT(m_Id);

    // The render pass calls the Update method every frame, to initialize, update, or dispose of the textures.
    public void Update(RenderTextureDescriptor textureDescriptor)
    {
        // Dispose of the textures if the memory needs to be reallocated.
        if (m_DescKey != Hash128.Compute(ref textureDescriptor))
            ReleaseHistoryFrameRT(m_Id);

        // Allocate the memory for the textures if it's not already allocated.
        if (currentTexture == null)
        {
            AllocHistoryFrameRT(m_Id, 2, ref textureDescriptor, "HistoryTexture");
    
            // Store the descriptor and hash key for future changes.
            m_Descriptor = textureDescriptor;
            m_DescKey = Hash128.Compute(ref textureDescriptor);
        }
    }
}

以下は、テクスチャに書き込むレンダーパスの例です。

class WriteToHistoryTexture : ScriptableRenderPass
{
    private class PassData
    {
        internal Material material;
    }

    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
    {
        var cameraData = frameData.Get<UniversalCameraData>();

        cameraData.historyManager.RequestAccess<ExampleHistory>();
        var history = cameraData.historyManager.GetHistoryForWrite<ExampleHistory>();

        if (history != null)
        {
            // Call the Update method of the camera history type.
            history.Update(cameraData.cameraTargetDescriptor);

            using (var builder = renderGraph.AddRasterRenderPass<PassData>("Write to history texture", out var passData))
            {
                UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
                RTHandle historyTexture = history?.currentTexture(multipassId);

                // Set the render graph to render to the history texture.
                builder.SetRenderAttachment(renderGraph.ImportTexture(historyTexture), 0, AccessFlags.Write);

                passData.material = m_Material;

                builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
                {
                    // Draw a triangle to the history texture
                    context.cmd.DrawProcedural(Matrix4x4.identity, data.material, 0, MeshTopology.Triangles, 3, 1);
                });
            }
        }
    }
}
URP で前のフレームのデータを取得する
URP のフレームバッファフェッチによる現在のフレームバッファの取得