版本:Unity 6 (6000.0)
语言:English
获取 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 中的帧缓冲区获取获取当前帧缓冲区