要将您自己的纹理添加到相机一个组件,用于创建场景中特定视点的图像。输出要么绘制到屏幕上,要么作为纹理捕获。更多信息
参见 术语表历史记录并在后面的帧中读取数据,请创建一个相机历史记录类型来存储帧之间的纹理。
按照以下步骤操作
创建一个继承自CameraHistoryItem
的类。例如
public class ExampleHistoryType : CameraHistoryItem {
...
}
在类中,为相机历史记录系统添加一个 ID。例如
private int uniqueId;
该 ID 表示一个纹理的完整历史记录,包括当前帧和之前的帧。
您还可以添加任何其他所需数据,例如您需要在帧之间存储的纹理描述符。
覆盖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);
}
为当前和之前的纹理创建公共属性,以便渲染通道可以访问它们。例如
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");
如果渲染通道写入具有不同大小或格式的纹理,您可能还需要在每一帧重新分配内存。
要写入您创建的纹理,请按照以下步骤操作
要在ScriptableRenderPass
类中请求访问纹理,请使用RequestAccess
API 和您的相机历史记录类型。例如
cameraData.historyManager.RequestAccess<ExampleHistoryType>();
获取当前帧的写入纹理,并将其转换为渲染图系统可以使用的句柄。例如
// 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);
});
}
}
}
}