Добавить текстуры в историю камеры
Чтобы добавить собственную текстуру в историю камеры и считывать данные в последующих кадрах, создайте тип истории камеры для хранения текстуры между кадрами.
Создание типа журнала камеры
Выполните следующие действия:
-
Создайте класс, наследующий
CameraHistoryItem. Например:public class ExampleHistoryType : CameraHistoryItem { ... } -
В этом классе добавьте идентификатор для системы истории камеры. Например:
private int uniqueId;Идентификатор представляет собой полную историю текстуры, включая текущий и предыдущие кадры.
Вы также можете добавить любые другие необходимые данные, например, дескриптор текстуры, который нужно хранить между кадрами.
-
Переопределить
OnCreateметод. В методе, вызватьOnCreateметод родительского класса и сформируйте уникальный идентификатор. Например: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); } -
Создайте открытые свойства для текущей и предыдущей текстур, чтобы проходы рендеринга могли к ним обращаться. Например:
public RTHandle currentTexture => GetCurrentFrameRT(uniqueId); public RTHandle previousTexture => GetPreviousFrameRT(uniqueId); -
Выделить память для текстуры. Например:
// Allocate 2 textures using a texture descriptor, assign them to the uniqueId, and give them a name. AllocHistoryFrameRT(uniqueId, 2, ref textureDescriptor, "ExampleHistoryTexture"); -
Реализуйте метод
Resetдля освобождения текстур истории, когда система истории камеры сбрасывает тип. Например:public override void Reset() { ReleaseHistoryFrameRT(uniqueId); }
Также может потребоваться перераспределять память для каждого кадра, если проход рендеринга записывает текстуру с другим размером или форматом.
Запись в текстуру
Для записи в созданную текстуру выполните следующие действия:
-
Чтобы запросить доступ к текстуре в
ScriptableRenderPassкласс, используйтеRequestAccessAPI с типом истории камеры. Например:cameraData.historyManager.RequestAccess<ExampleHistoryType>(); -
Получить текстуру для текущего кадра для записи и преобразовать ее в handle, который может использовать графическая система рендеринга. Например:
// Get the textures ExampleHistoryType history = cameraData.historyManager.GetHistoryForWrite<ExampleHistoryType>(); // Get the texture for the current frame RTHandle historyTexture = history?.currentTexture; // Convert the texture into a handle the render graph system can use historyTexture = renderGraph.ImportTexture(historyTexture);
Затем вы можете записать текстуру в свой проход рендеринга. Более подробную информацию см. в Использование текстур.
Читать из текстуры
Чтобы прочитать текстуру, используйте RequestAccess API с созданным типом истории камеры.
Вы должны записать текстуру, прежде чем читать из нее.
Дополнительные сведения см. в Получить данные из предыдущих кадров.
Примеры
Ниже приведен пример типа истории камеры.
using UnityEngine;
using UnityEngine.Rendering;
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);
}
// Release the history GPU resources (textures) when the camera history system resets the type.
public override void Reset()
{
ReleaseHistoryFrameRT(m_Id);
}
public RTHandle currentTexture => GetCurrentFrameRT(m_Id);
public RTHandle previousTexture => 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);
}
}
}
Ниже приведен пример прохода рендеринга, который записывает текстуру. Вы можете использовать материал URP в качестве materialи Scriptable Renderer Feature для введения прохода рендеринга в конвейер рендеринга.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
class WriteToHistoryTexture : ScriptableRenderPass
{
// Property for the custom material that writes to the history texture.
public Material m_Material;
class PassData
{
public Material material;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var cameraData = frameData.Get<UniversalCameraData>();
// Request access to the history texture.
cameraData.historyManager.RequestAccess<ExampleHistoryType>();
var history = cameraData.historyManager.GetHistoryForWrite<ExampleHistoryType>();
if (history != null)
{
// Make the history a color-only texture to match the camera target.
var historyDesc = cameraData.cameraTargetDescriptor;
historyDesc.depthBufferBits = 0;
historyDesc.msaaSamples = 1;
// Call the Update method of the camera history type.
history.Update(historyDesc);
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Write to history texture", out var passData))
{
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
RTHandle historyTexture = history?.currentTexture;
// 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);
});
}
}
}
}