study/first_study/Library/PackageCache/com.unity.render-pipelines.universal@d10049dfa479/Samples~/URPRenderGraphSamples/TextureReferenceWithFrameData/TextureRefRendererFeature.cs
jh04010421 739d49f1a0 Unity | 2026.01.20
수업 실습 파일
2026-01-20 11:01:57 +09:00

140 lines
6.1 KiB
C#

using UnityEngine;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule.Util;
// In this example we will create a texture reference ContextItem in frameData to hold a reference
// used by future passes. This is useful to avoid additional blit operations copying back and forth
// to the camera's color attachment. Instead of copying it back after the blit operation we can instead
// update the reference to the blit destination and use that for future passes.
// The frameData is the preferred way to share resources between passes. Previously, it was common to use global textures for this.
// However, it's better to avoid using global textures where you can.
public class TextureRefRendererFeature : ScriptableRendererFeature
{
// The ContextItem used to store the texture reference at.
public class TexRefData : ContextItem
{
// The texture reference variable.
public TextureHandle texture = TextureHandle.nullHandle;
// Reset function required by ContextItem. It should reset all variables not carried
// over to next frame.
public override void Reset()
{
// We should always reset texture handles since they are only valid for the current frame.
texture = TextureHandle.nullHandle;
}
}
// This pass updates the reference when making a blit operation using a material and the camera's color attachment.
class UpdateRefPass : ScriptableRenderPass
{
// Material used in the blit operation.
Material[] m_DisplayMaterials;
// Function used to transfer the material from the renderer feature to the render pass.
public void Setup(Material[] materials)
{
m_DisplayMaterials = materials;
}
// This function blits the whole screen for a given material.
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
foreach (var mat in m_DisplayMaterials)
{
// Skip material if it is null.
if (mat == null)
{
Debug.LogWarning($"Skipping render pass for unassigned material.");
continue;
}
var texRefExist = frameData.Contains<TexRefData>();
var texRef = frameData.GetOrCreate<TexRefData>();
// First time running this pass. Fetch ref from active color buffer.
if (!texRefExist)
{
var resourceData = frameData.Get<UniversalResourceData>();
// For this first occurrence we would like:
texRef.texture = resourceData.activeColorTexture;
}
// Create the destination texture for the pass.
var descriptor = texRef.texture.GetDescriptor(renderGraph);
// We disable MSAA for the blit operations.
descriptor.msaaSamples = MSAASamples.None;
descriptor.name = $"BlitMaterialRefTex_{mat.name}";
descriptor.clearBuffer = false;
// Create a new temporary texture to keep the blit result.
var destination = renderGraph.CreateTexture(descriptor);
// Fill in the pass data used by the render function.
var blitPassParams = new RenderGraphUtils.BlitMaterialParameters(texRef.texture, destination, mat, 0);
renderGraph.AddBlitPass(blitPassParams, $"UpdateRefPass_{mat.name}");
// Update the texRef.
texRef.texture = destination;
}
}
}
// After updating the reference we will need to use the result copying it back to camera's
// color attachment.
class CopyBackRefPass : ScriptableRenderPass
{
// This function blits the reference back to the camera's color attachment.
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
// Early exit if TexRefData doesn't exist within frameData since there is nothing to copy back.
if (!frameData.Contains<TexRefData>()) return;
// Fetch UniversalResourceData to retrieve the camera's active color texture.
var resourceData = frameData.Get<UniversalResourceData>();
// Fetch TexRefData to retrieve the texture reference.
var texRef = frameData.Get<TexRefData>();
renderGraph.AddBlitPass(texRef.texture, resourceData.activeColorTexture, Vector2.one, Vector2.zero, passName: "Blit Back Pass");
}
}
[Tooltip("The material used when making the blit operation.")]
public Material[] displayMaterials = new Material[1];
UpdateRefPass m_UpdateRefPass;
CopyBackRefPass m_CopyBackRefPass;
// Here you can create passes and do the initialization of them. This is called every time serialization happens.
public override void Create()
{
m_UpdateRefPass = new UpdateRefPass();
m_CopyBackRefPass = new CopyBackRefPass();
// Configures where the render pass should be injected.
m_UpdateRefPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
m_CopyBackRefPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
// Here you can inject one or multiple render passes in the renderer.
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
// Early exit if there are no materials.
if (displayMaterials == null)
{
Debug.LogWarning("TexterRefRendererFeature materials is null and will be skipped.");
return;
}
// Since they have the same RenderPassEvent the order matters when enqueueing them.
m_UpdateRefPass.Setup(displayMaterials);
renderer.EnqueuePass(m_UpdateRefPass);
renderer.EnqueuePass(m_CopyBackRefPass);
}
}