Skip to content

Unity URP Render Graph

Unity 6부터 URP의 렌더링 파이프라인은 Render Graph 시스템으로 전환되었습니다. 기존 ScriptableRenderPass 방식의 수동 리소스 관리를 대체하며, 프레임별 렌더 패스 의존성을 그래프로 선언해 드라이버가 최적 실행 순서를 결정합니다.


기존 방식에서는 개발자가 직접 RT(RenderTexture) 생성·바인딩·해제를 관리해야 했습니다. Render Graph는 이 과정을 선언적(declarative) 으로 바꿉니다.

  • 리소스 수명 자동 관리 — 사용하지 않는 RT를 드라이버가 자동 해제
  • 패스 컬링 — 최종 출력에 기여하지 않는 패스를 자동으로 제거
  • 비동기 컴퓨트 지원 — 그래프 의존성을 기반으로 비동기 디스패치를 자동 스케줄

타입역할
RenderGraph프레임당 그래프 컨텍스트 관리
RenderGraphBuilder패스 등록 및 리소스 선언
TextureHandle그래프 내 텍스처 리소스 핸들
BufferHandle그래프 내 컴퓨트 버퍼 핸들

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
public class GrayscaleRendererFeature : ScriptableRendererFeature
{
GrayscalePass _pass;
public override void Create()
{
_pass = new GrayscalePass();
_pass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(_pass);
}
}
public class GrayscalePass : ScriptableRenderPass
{
static readonly int s_BlitTexture = Shader.PropertyToID("_BlitTexture");
// 패스에서 사용할 데이터를 담는 구조체
private class PassData
{
public TextureHandle source;
public TextureHandle destination;
public Material material;
}
Material _material;
public GrayscalePass()
{
_material = new Material(Shader.Find("Custom/Grayscale"));
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var resourceData = frameData.Get<UniversalResourceData>();
// 소스 텍스처 (현재 카메라 컬러 버퍼)
TextureHandle source = resourceData.activeColorTexture;
// 임시 RT 선언 — 수명을 Render Graph가 관리
var desc = renderGraph.GetTextureDesc(source);
desc.name = "GrayscaleTempRT";
TextureHandle destination = renderGraph.CreateTexture(desc);
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Grayscale Pass", out var passData))
{
passData.source = source;
passData.destination = destination;
passData.material = _material;
// 읽기/쓰기 선언 (의존성 선언)
builder.UseTexture(source, AccessFlags.Read);
builder.SetRenderAttachment(destination, 0, AccessFlags.Write);
builder.SetRenderFunc(static (PassData data, RasterGraphContext ctx) =>
{
data.material.SetTexture(s_BlitTexture, data.source);
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0);
});
}
// 카메라 출력을 변환된 텍스처로 교체
resourceData.cameraColor = destination;
}
}

// ❌ 잘못된 방식 — 매 프레임 RenderTexture 직접 생성
var rt = new RenderTexture(desc);
// ✅ 올바른 방식 — Render Graph에 선언, 자동 풀링
TextureHandle handle = renderGraph.CreateTexture(desc);

CreateTexture로 선언된 핸들은 해당 프레임에만 유효하며, 다음 프레임에 자동으로 풀(pool)에 반환됩니다.

출력 결과가 최종 화면에 기여하지 않으면 패스가 컬링됩니다. 반드시 최종 색상 버퍼에 결과를 기록하거나, builder.AllowPassCulling(false)를 설정해야 합니다.

// 디버그 렌더처럼 컬링을 막아야 할 경우
builder.AllowPassCulling(false);

항목권장 방법
RT 재사용ImportTexture 대신 CreateTexture로 풀링 활용
Blit 최소화패스를 합쳐 Blit 횟수 감소
비동기 컴퓨트AddComputePass + 독립적인 리소스 사용 선언
프로파일링Frame Debugger → Render Graph Viewer로 패스 의존성 시각화