レンダーパス間でテクスチャを転送できます。例えば、あるレンダーパスでテクスチャを作成し、後で作成したレンダーパスで使用することが必要な場合が考えられます。
レンダーパス間でテクスチャを転送するには、以下の方法を使用します。
テクスチャをレンダーパスの外部、例えばスクリプタブルレンダラー機能の TextureHandle として保存することもできます。
テクスチャを複数のフレームで使用可能にする必要がある場合、または複数のカメラがテクスチャにアクセスできるようにする必要がある場合は、代わりにレンダーグラフシステムにテクスチャをインポートするを参照してください。
テクスチャをフレームデータに追加して、後のレンダーパスでテクスチャをフェッチできます。
以下の手順に従ってください。
ContextItem を継承し、テクスチャハンドルフィールドを含むクラスを作成します。
例:
public class MyCustomData : ContextItem {
public TextureHandle textureToTransfer;
}
クラスに Reset() メソッドを実装して、フレームのリセット時にテクスチャをリセットする必要があります。
例:
public class MyCustomData : ContextItem {
public TextureHandle textureToTransfer;
public override void Reset()
{
textureToTransfer = TextureHandle.nullHandle;
}
}
RecordRenderGraph メソッドで、クラスのインスタンスをフレームデータに追加します。
例:
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Get frame data", out var passData))
{
UniversalResourceData resourceData = frameContext.Get<UniversalResourceData>();
var customData = contextData.Create<MyCustomData>();
}
}
テクスチャハンドルをテクスチャに設定します。
例:
// Create texture properties that match the screen
RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
// Create the texture
TextureHandle texture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);
// Set the texture in the custom data instance
customData.textureToTransfer = texture;
後のレンダーパスの RecordRenderGraph メソッドで、カスタムデータを取得してテクスチャを取得できます。
例:
// Get the custom data
MyCustomData fetchedData = frameData.Get<MyCustomData>();
// Get the texture
TextureHandle customTexture = customData.textureToTransfer;
フレームデータの詳細については、フレームデータの使用を参照してください。
以下の例では、テクスチャを含む CustomData クラスを追加しています。最初のレンダーパスはテクスチャをクリアして黄色にし、2 番目のレンダーパスは黄色のテクスチャを取得してその上に三角形形を描画します。
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;
public class AddOwnTextureToFrameData : ScriptableRendererFeature
{
AddOwnTexturePass customPass1;
DrawTrianglePass customPass2;
public override void Create()
{
customPass1 = new AddOwnTexturePass();
customPass2 = new DrawTrianglePass();
customPass1.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
customPass2.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(customPass1);
renderer.EnqueuePass(customPass2);
}
// Create the first render pass, which creates a texture and adds it to the frame data
class AddOwnTexturePass : ScriptableRenderPass
{
class PassData
{
internal TextureHandle copySourceTexture;
}
// Create the custom data class that contains the new texture
public class CustomData : ContextItem {
public TextureHandle newTextureForFrameData;
public override void Reset()
{
newTextureForFrameData = TextureHandle.nullHandle;
}
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Create new texture", out var passData))
{
// Create a texture and set it as the render target
RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
TextureHandle texture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);
CustomData customData = frameContext.Create<CustomData>();
customData.newTextureForFrameData = texture;
builder.SetRenderAttachment(texture, 0, AccessFlags.Write);
builder.AllowPassCulling(false);
builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));
}
}
static void ExecutePass(PassData data, RasterGraphContext context)
{
// Clear the render target (the texture) to yellow
context.cmd.ClearRenderTarget(true, true, Color.yellow);
}
}
// Create the second render pass, which fetches the texture and writes to it
class DrawTrianglePass : ScriptableRenderPass
{
class PassData
{
// No local pass data needed
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Fetch texture and draw triangle", out var passData))
{
// Fetch the yellow texture from the frame data and set it as the render target
var customData = frameContext.Get<AddOwnTexturePass.CustomData>();
var customTexture = customData.newTextureForFrameData;
builder.SetRenderAttachment(customTexture, 0, AccessFlags.Write);
builder.AllowPassCulling(false);
builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));
}
}
static void ExecutePass(PassData data, RasterGraphContext context)
{
// Generate a triangle mesh
Mesh mesh = new Mesh();
mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0) };
mesh.triangles = new int[] { 0, 1, 2 };
// Draw a triangle to the render target (the yellow texture)
context.cmd.DrawMesh(mesh, Matrix4x4.identity, new Material(Shader.Find("Universal Render Pipeline/Unlit")));
}
}
}
ゲームオブジェクトのシェーダーの入力としてテクスチャを使用する必要がある場合は、テクスチャをグローバルテクスチャとして設定できます。グローバルテクスチャは、すべてのシェーダーとレンダーパスで使用できます。
テクスチャをグローバルテクスチャとして設定すると、レンダリングが低速になる場合があります。SetGlobalTexture を参照してください。
エラーが発生する可能性があるため、安全でないレンダーパスと CommandBuffer.SetGlobal を使用してテクスチャをグローバルテクスチャとして設定しないでください。
グローバルテクスチャを設定するには、RecordRenderGraph メソッドで、SetGlobalTextureAfterPass メソッドを使用します。
例:
// Allocate a global shader texture called _GlobalTexture
private int globalTextureID = Shader.PropertyToID("_GlobalTexture")
using (var builder = renderGraph.AddRasterRenderPass<PassData>("MyPass", out var passData)){
// Set a texture to the global texture
builder.SetGlobalTextureAfterPass(texture, globalTextureID);
}
まだ SetRenderFunc を呼び出していない場合は、空のレンダー関数も追加する必要があります。例:
builder.SetRenderFunc((PassData data, RasterGraphContext context) => { });
これで以下のことが可能になります。
UseGlobalTexture() API または UseAllGlobalTextures() API を使用して、異なるレンダーパスのテクスチャにアクセスします。