Version: Unity 6.0 (6000.0)
语言 : 中文
在 URP 中获取先前帧的数据
在 URP 中通过帧缓冲区获取来获取当前帧缓冲区

将纹理添加到摄像机历史记录

要将您自己的纹理添加到摄像机历史记录并在以后的帧中读取该数据,请创建一个摄像机历史记录类型来存储帧之间的纹理。

创建摄像机历史记录类型

请遵循以下步骤:

  1. 创建一个继承自 CameraHistoryItem 的类。例如:

    public class ExampleHistoryType : CameraHistoryItem {
        ...
    }
    
  2. 在该类中,添加摄像机历史记录系统的 ID。例如:

        private int uniqueId;
    

    该 ID 表示一个纹理的完整历史记录,包括当前和先前的帧。

    还可以添加所需的任何其他数据,例如需要在帧之间存储的纹理描述符。

  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 中通过帧缓冲区获取来获取当前帧缓冲区