TECHARTNOMAD | TECHARTFLOWIO.COM

UNITY3D

URP의 Unity 렌더 그래프 시스템

jplee 2024. 9. 28. 17:16

유니티 공식 문서 렌더그래프 시스템 소개부터 활용까지의 내용을 소개 합니다.

 


URP의 렌더 그래프 시스템 소개

렌더 그래프 시스템은 유니버설 렌더 파이프라인(URP)에서 스크립터블 렌더 패스를 작성하는 데 사용하는 API 세트입니다.

렌더 그래프 API를 사용하여 스크립터블 렌더 패스를 생성할 때 URP에 다음을 알려줍니다:

  1. 사용할 텍스처 또는 렌더 텍스처입니다. 이 단계는 레코딩 단계입니다.
  2. 레코딩 단계의 텍스처 또는 렌더 텍스처를 사용하여 실행할 그래픽 명령입니다. 이 단계는 실행 단계입니다.

그런 다음 스크립터블 렌더 패스를 URP 렌더러에 추가할 수 있습니다. 스크립터블 렌더 패스는 URP의 내부 렌더 그래프의 일부가 되며, 이는 각 프레임을 통과하는 렌더 패스 URP 단계의 시퀀스입니다. URP는 렌더 패스와 렌더 그래프를 자동으로 최적화하여 렌더 패스 수와 렌더 패스가 사용하는 메모리 및 대역폭을 최소화합니다.

URP가 렌더링을 최적화하는 방법

  • URP는 렌더 그래프에서 렌더링을 최적화하기 위해 다음을 수행합니다.
  • 여러 렌더 패스를 단일 렌더 패스로 병합합니다.
  • 프레임이 사용하지 않는 리소스를 할당하지 않습니다.
  • 최종 프레임이 출력을 사용하지 않는 경우 렌더 패스를 실행하지 않습니다.
  • 예를 들어 동일한 속성을 가진 두 개의 텍스처를 하나의 텍스처로 대체하는 등 리소스 중복을 방지합니다.
  • 컴퓨팅 및 그래픽 GPU 명령 대기열을 자동으로 동기화합니다.

타일 기반 지연 렌더링(TBDR)을 사용하는 모바일 플랫폼에서 URP는 여러 렌더 패스를 하나의 네이티브 렌더 패스로 결합할 수도 있습니다. 네이티브 렌더 패스는 GPU에서 CPU로 텍스처를 복사하는 대신 타일 메모리에 텍스처를 유지합니다. 따라서 URP는 메모리 대역폭과 렌더링 시간을 덜 사용합니다.

URP가 커스텀 렌더 패스에서 렌더링을 최적화하는 방법을 확인하려면 렌더 그래프 분석을 참조하세요.

 

URP의 렌더 그래프 시스템을 사용하여 렌더 패스를 작성합니다.

이 페이지에서는 렌더 그래프 시스템을 사용하여 렌더 패스를 작성하는 방법을 설명합니다.

설명을 설명하기 위해 이 페이지에서는 카메라
의 활성 색상 텍스처를 대상 텍스처로 복사하는 렌더 패스 예제를 사용합니다. 코드를 단순화하기 위해 이 예제에서는 프레임의 다른 곳에서는 대상 텍스처를 사용하지 않습니다. 프레임 디버거를 사용하여 내용을 검사할 수 있습니다.

렌더 패스 선언

 스크립터블 렌더 패스 클래스를 상속하는 클래스로 렌더 패스를 선언합니다.

렌더 패스가 사용하는 리소스를 선언합니다.

렌더 패스 내에서 렌더 패스가 사용하는 리소스를 포함하는 클래스를 선언합니다.

리소스는 일반 C# 변수와 렌더 그래프 리소스 참조가 될 수 있습니다. 렌더링 그래프 시스템은 렌더링 코드 실행 중에 이 데이터 구조에 액세스할 수 있습니다. 렌더 패스에서 사용하는 변수만 선언해야 합니다. 불필요한 변수를 추가하면 성능이 저하될 수 있습니다.

class PassData
{
    internal TextureHandle copySourceTexture;
}

RecordRenderGraph 메서드는 데이터를 채우고 렌더 그래프는 이를 렌더링 함수에 파라미터로 전달합니다.

렌더 패스에 대한 렌더링 명령을 생성하는 렌더링 함수를 선언합니다.

렌더 패스에 대한 렌더링 명령을 생성하는 렌더링 함수를 선언합니다. 또한 이 예제에서 RecordRenderGraph 메서드는 렌더 그래프가 SetRenderFunc 메서드를 사용하여 함수를 사용하도록 지시합니다.

static void ExecutePass(PassData data, RasterGraphContext context)
{
    // 소스 텍스처의 내용을 복사하거나 블릿하는 렌더링 명령을 기록합니다.
    // 내용을 렌더 패스의 컬러 렌더 타깃에 복사 또는 블릿하는 렌더링 명령을 기록합니다.
    // RecordRenderGraph 메서드는 UseTextureFragment 메서드를 사용하여 
    // 대상 텍스처를 렌더 타깃으로 설정합니다.
    Blitter.BlitTexture(context.cmd, data.copySourceTexture,
        new Vector4(1, 1, 0, 0), 0, false);
}

RecordRenderGraph 메서드 구현하기

RecordRenderGraph 메서드를 사용하여 렌더 그래프 시스템에서 하나 이상의 렌더 패스를 추가하고 구성할 수 있습니다.

Unity는 렌더 그래프 구성 단계에서 이 메서드를 호출하여 렌더 그래프 실행을 위한 관련 패스 및 리소스를 등록할 수 있습니다. 이 메서드를 사용하여 커스텀 렌더링을 구현할 수 있습니다.

RecordRenderGraph 메서드에서는 렌더 패스 입력 및 출력을 선언하지만 명령 버퍼에 명령을 추가하지 않습니다.

다음 섹션에서는 RecordRenderGraph 메서드의 주요 요소에 대해 설명하고 구현 예제를 제공합니다.

 

렌더 그래프 빌더 변수는 프레임 리소스를 추가합니다.

builder 변수는 IRasterRenderGraphBuilder 인터페이스의 인스턴스입니다. 이 변수는 렌더 패스와 관련된 정보를 구성하기 위한 진입점입니다.

UniversalResourceData 클래스에는 카메라의 활성 색상 및 뎁스 텍스처를 포함하여 URP에서 사용하는 모든 텍스처 리소스가 포함됩니다.

UniversalCameraData 클래스에는 현재 활성화된 카메라와 관련된 데이터가 포함되어 있습니다.

이 샘플은 데모를 위해 임시 대상 텍스처를 생성합니다. UniversalRenderer.CreateRenderGraphTexture는 RenderGraph.CreateTexture 메서드를 호출하는 헬퍼 메서드입니다.

TextureHandle destination =
    UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "CopyTexture", false);

builder.UseTexture 메서드는 이 렌더 패스가 소스 텍스처를 읽기 전용 입력으로 사용한다고 선언합니다:

builder.UseTexture(passData.copySourceTexture);

이 예제에서 builder.SetRenderAttachment 메서드는 이 렌더 패스가 임시 대상 텍스처를 색상 렌더링 대상으로 사용한다고 선언합니다. 이 선언은 호환성 모드(렌더 그래프 API 없이)에서 사용할 수 있는 cmd.SetRenderTarget API와 유사합니다.

SetRenderFunc 메서드는 렌더 패스를 실행할 때 그래프 호출을 렌더링하는 렌더링 함수로 ExecutePass 메서드를 설정합니다. 이 샘플은 메모리 할당을 피하기 위해 람다 표현식을 사용합니다.


 

람다 식 - 람다 식 및 무명 함수 - C# reference

익명 함수 및 식 본문 멤버를 만드는 데 사용되는 C# 람다 식입니다.

learn.microsoft.com

builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));

RecordRenderGraph 메서드의전체 예제입니다 :

// 이 메서드는 렌더 그래프에 하나 이상의 렌더 패스를 추가하고 구성합니다.
// 이 프로세스에는 입력과 출력을 선언하는 것이 포함됩니다,
// 명령 버퍼에 명령을 추가하는 것은 포함되지 않습니다.
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
    string passName = "Copy To Debug Texture";

    // 렌더 그래프에 래스터 렌더 패스를 추가합니다. 
    // PassData 유형 매개변수는 passData 출력 변수의 유형을 결정합니다.
    using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName,
        out var passData))
    {
        // 유니버설리소스데이터에는 카메라의 활성 색상 및 뎁스 텍스처를 포함하여 
        // URP에서 사용하는 모든 텍스처 레퍼런스가 포함되어 있습니다.
        UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();

        // 렌더 패스의 렌더링 함수에 
        // 필요한 데이터로 passData를 채웁니다. 
        // 카메라의 활성 컬러 텍스처를 복사 작업의 소스 텍스처로 
        // 사용합니다.
        passData.copySourceTexture = resourceData.activeColorTexture;

        // 카메라가 사용하는 텍스처의 설정(예: 치수)에 따라 복사 작업의 대상 텍스처를 만듭니다. 
        // 멀티샘플링되지 않은 대상 텍스처를 얻으려면 msaaSamples를 1로 설정합니다. 
        // CreateRenderGraphTexture 메서드가 깊이 텍스처가 아닌 컬러 텍스처를 생성하도록 하려면 
        // depthBufferBits를 0으로 설정합니다.
        UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
        RenderTextureDescriptor desc = cameraData.cameraTargetDescriptor;
        desc.msaaSamples = 1;
        desc.depthBufferBits = 0;

        // 이 샘플은 데모를 위해 임시 대상 텍스처를 생성합니다.
        // 유니버설 렌더러.CreateRenderGraphTexture는 RenderGraph.CreateTexture 메서드를 
        // 호출하는 헬퍼 메서드입니다.
        // 텍스트처 디스크립터 인스턴스 대신 렌더텍스처 디스크립터 인스턴스를 사용하면 코드가 
        // 간소화됩니다.
        TextureHandle destination =
            UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc,
                "CopyTexture", false);

        // 이 렌더 패스가 소스 텍스처를 읽기 전용 입력으로 사용하도록 선언합니다.
        builder.UseTexture(passData.copySourceTexture);

        // 이 렌더 패스가 임시 대상 텍스처를 
        // 컬러 렌더링 타깃으로 사용한다고 선언합니다. 
        // 이는 RenderGraph API 이전의 cmd.SetRenderTarget과 유사합니다.
        builder.SetRenderAttachment(destination, 0);

        // 임시 대상 텍스처에 저장된 결과가 다른 패스에서 
        // 사용되지 않기 때문에 
        // 렌더그래프는 자동으로 이 렌더 패스를 제거할 수 있다고 판단합니다. 
        // 데모용으로 이 샘플에서는 이 동작을 꺼서 
        // 렌더 그래프가 렌더 패스를 실행하는지 확인합니다.
        builder.AllowPassCulling(false);

        // 그래프 호출을 렌더링하는 렌더링 함수로 ExecutePass 메서드를 
        // 렌더링 패스로 설정합니다. 
        // 이 샘플은 메모리 할당을 피하기 위해 람다 표현식을 사용합니다.
        builder.SetRenderFunc((PassData data, RasterGraphContext context)
            => ExecutePass(data, context));
    }
}

 

스크립터블 렌더 패스 인스턴스를 렌더러에 주입합니다.

스크립터블 렌더 패스 인스턴스를 렌더러에 주입하려면 렌더러 기능 구현에서 AddRenderPasses 메서드를 사용합니다. URP는 매 프레임마다 각 카메라에 대해 한 번씩 AddRenderPasses 메서드를 호출합니다.

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
    renderer.EnqueuePass(m_CopyRenderPass);
}

 

URP의 렌더 그래프 시스템 내 텍스처

유니버설 렌더 파이프라인(URP)의 커스텀 렌더 패스에서 텍스처에 액세스하고 사용하는 방법.

페이지 설명

Create a texture in the render graph system 렌더 그래프 시스템 렌더 패스에서 텍스처를 생성합니다.
Import a texture into the render graph system 렌더 그래프 시스템 렌더 패스에서 렌더 텍스처( )를 생성하거나 사용하려면 RTHandle API를 사용합니다.
Use a texture in a render pass 렌더 패스가 텍스처를 읽거나 쓸 수 있도록 하려면 렌더 그래프 시스템 API를 사용하여 텍스처를 입력 또는 출력으로 설정하세요.
Transfer a texture between passes 텍스처를 전역 텍스처로 설정하거나 프레임 데이터에 텍스처를 추가합니다.
Best practice for blitting URP에서 blit 작업을 수행하는 다양한 방법과 커스텀 렌더 패스를 작성할 때 따라야 할 모범 사례를 이해합니다.

프레임 데이터 사용

 

Unity - Manual: Get data from the current frame in URP

Frame data in the render graph system in URP Get data from previous frames in URP Get data from the current frame in URP You can fetch the textures that the Universal Render PipelineA series of operations that take the contents of a Scene, and displays the

docs.unity3d.com

URP의 렌더 그래프 시스템에서 텍스처 만들기

렌더 그래프 시스템에서 텍스처를 생성하려면 유니버설 렌더러.CreateRenderGraphTexture API를 사용합니다.

유니버설 렌더 파이프라인이 렌더 그래프를 최적화할 때 최종 프레임에서 텍스처를 사용하지 않는 경우 렌더 패스가 사용하는 메모리와 대역폭을 줄이기 위해 텍스처를 생성하지 않을 수 있습니다. URP가 렌더 그래프를 최적화하는 방법에 대한 자세한 내용은 렌더 그래프 시스템 소개를 참조하세요.


여러 프레임 또는 여러 카메라에서 텍스처를 사용하는 방법에 대한 자세한 내용은 프로젝트에서 가져온 텍스처 에셋(예: 텍스처 자산)을 렌더 그래프 시스템으로 가져오기를 참조하세요.

텍스처 생성

텍스처를 생성하려면 스크립터블 렌더패스 클래스의 RecordRenderGraph 메서드에서 다음 단계를 따르세요:

  1. 필요한 텍스처 프로퍼티가 포함된 RenderTextureDescriptor 오브젝트를 생성합니다.
  2. Use the UniversalRenderer.CreateRenderGraphTexture method to create a texture and return a texture handle.

예를 들어 다음은 화면과 같은 크기의 텍스처를 만듭니다.

RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
TextureHandle textureHandle = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);

그런 다음 동일한 커스텀 렌더 패스에서 텍스처를 사용할 수 있습니다.

현재 카메라만 텍스처에 액세스할 수 있습니다. 다른 카메라나 커스텀 렌더링 코드 등 다른 곳에서 텍스처에 액세스하려면 대신 텍스처를 임포트하세요.

렌더 그래프 시스템은 CreateRenderGraphTexture로 생성한 텍스처의 수명을 관리하므로 텍스처를 완성할 때 사용하는 메모리를 수동으로 해제할 필요가 없습니다.

예제

다음 스크립터블 렌더러 기능에는 텍스처를 생성하고 노란색으로 지우는 렌더링 패스 예제가 포함되어 있습니다. 렌더 파이프라인에 렌더 패스를 추가하는 방법에 대한 자세한 내용은 스크립터블 렌더러 기능을 사용하여 패스 주입을 참조하세요.

프레임 디버거를 사용하여 렌더 패스가 추가하는 텍스처를 확인합니다.

using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;

public class CreateYellowTextureFeature : ScriptableRendererFeature
{
    CreateYellowTexture customPass;

    public override void Create()
    {
        customPass = new CreateYellowTexture();
        customPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(customPass);
    }

    class CreateYellowTexture : ScriptableRenderPass
    {
        class PassData
        {
            internal TextureHandle cameraColorTexture;
        }

        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
        {
            using (var builder = renderGraph.AddRasterRenderPass<PassData>("Create yellow texture", out var passData))
            {
                // 화면 크기에 맞는 텍스처 프로퍼티 만들기
                RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);

                // 임시 텍스처 생성하기
                TextureHandle texture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);

                // 텍스처를 렌더 타깃으로 설정합니다.
                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)
        {          
            // 렌더링 대상을 노란색으로 지우기
            context.cmd.ClearRenderTarget(true, true, Color.yellow);            
        }
    }

}

다른 예시는 유니버설 렌더 파이프라인(URP) 패키지 샘플에서OutputTexture라는예시를 참조하세요 .

 

텍스처를 URP의 렌더 그래프 시스템으로 임포트합니다.

렌더 패스 에서 렌더 그래프 시스템에서 텍스처를 생성하면 렌더 그래프 시스템이 텍스처의 생성 및 폐기를 처리합니다. 이 프로세스는 텍스처가 다음 프레임에 존재하지 않을 수 있으며 다른 카메라에서 텍스처를 사용하지 못할 수 있음을 의미합니다.

텍스처를 여러 프레임과 카메라에서 사용할 수 있도록 하려면 ImportTexture API를 사용하여 텍스처를 렌더 그래프 시스템으로 가져옵니다.

렌더 그래프 시스템 외부에서 생성된 텍스처를 사용하는 경우 텍스처를 가져올 수 있습니다. 예를 들어 텍스처 에셋과 같이 프로젝트의 텍스처를 가리키는 렌더 텍스처 를 생성하여 렌더 패스의 입력으로 사용할 수 있습니다.

렌더 그래프 시스템은 임포트된 텍스처의 수명을 관리하지 않습니다. 따라서 다음 사항이 적용됩니다:

  • 임포트한 렌더 텍스처를 폐기하여 사용 중인 메모리를 확보해야 완료할 수 있습니다.
  • URP는 임포트된 텍스처를 사용하는 렌더 패스를 컬링할 수 없습니다. 따라서 렌더링이 느려질 수 있습니다.

RTHandle API에 대한 자세한 내용은 RTHandle 시스템 사용하기를 참조하세요.

텍스처 가져오기

텍스처를 임포트하려면 스크립터블 렌더패스 클래스의 RecordRenderGraph 메서드에서 다음 단계를 따르세요:

1. RTHandle API를 사용하여 렌더 텍스처 핸들을 만듭니다.

예시:

private RTHandle renderTextureHandle;

2. 필요한 텍스처 프로퍼티가 포함된 RenderTextureDescriptor 오브젝트를 생성합니다.
예시:

RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);

3. 렌더 텍스처를 생성하고 렌더 텍스처 핸들에 첨부하려면 ReAllocateIfNeeded 메서드를 사용합니다. 이 메서드는 렌더 텍스처 핸들이 null이거나 렌더 텍스처가 렌더 텍스처 설명자와 다른 속성을 가진 경우에만 렌더 텍스처를 생성합니다.
예시:

RenderingUtils.ReAllocateIfNeeded(ref renderTextureHandle, textureProperties, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "My render texture" );

4. 텍스처를 임포트하여 렌더 그래프 시스템이 사용할 수 있는 TextureHandle 오브젝트로 변환합니다.
예시:

TextureHandle texture = renderGraph.ImportTexture(renderTextureHandle);

그런 다음 TextureHandle 오브젝트를 사용하여 렌더 텍스처를 읽거나 쓸 수 있습니다.

프로젝트에서 텍스처 임포트

프로젝트에서 머티리얼에 첨부된 텍스처와 같은 텍스처를 임포트하려면 다음 단계를 따르세요:

1. 외부 텍스처에서 렌더 텍스처 핸들을 생성하려면 RTHandles.Alloc API를 사용합니다.

예시:

RTHandle renderTexture = RTHandles.Alloc(texture);

텍스처를 임포트하여 렌더 그래프 시스템에서 사용할 수 있는 TextureHandle 오브젝트로 변환합니다.
예시:

TextureHandle textureHandle = renderGraph.ImportTexture(renderTexture);

 

그런 다음 TextureHandle 오브젝트를 사용하여 렌더 텍스처를 읽거나 쓸 수 있습니다.

 

렌더 텍스처 폐기

렌더링 패스가 끝날 때 렌더링 텍스처가 사용하는 메모리를 Dispose 메서드를 사용하여 해제해야 합니다.

public void Dispose()
{
    renderTexture.Release();
}

예제

다음 스크립터블 렌더러 기능에는 텍스처 에셋을 임시 텍스처에 복사하는 렌더 패스 예제가 포함되어 있습니다. 이 예제를 사용하려면 다음 단계를 따르세요:

  1. 이 스크립터블 렌더러 기능을 URP 에셋에 추가합니다. 스크립터블 렌더러 기능을 사용하여 패스 주입을 참조하십시오.
  2. URP 에셋의 인스펙터 창에서 사용할 텍스처 프로퍼티에 텍스처를 추가합니다.
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;

public class BlitFromExternalTexture : ScriptableRendererFeature
{
    // The texture to use as input 
    public Texture2D textureToUse;

    BlitFromTexture customPass;

    public override void Create()
    {
        // Create an instance of the render pass, and pass in the input texture 
        customPass = new BlitFromTexture(textureToUse);

        customPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(customPass);
    }

    class BlitFromTexture : ScriptableRenderPass
    {
        class PassData
        {
            internal TextureHandle textureToRead;
        }

        private Texture2D texturePassedIn;

        public BlitFromTexture(Texture2D textureIn)
        {
            // In the render pass's constructor, set the input texture
            texturePassedIn = textureIn;
        }

        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
        {
            using (var builder = renderGraph.AddRasterRenderPass<PassData>("Copy texture", out var passData))
            {
                // Create a temporary 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);
                builder.SetRenderAttachment(texture, 0, AccessFlags.Write);

                // Create a render texture from the input texture
                RTHandle rtHandle = RTHandles.Alloc(texturePassedIn);

                // Create a texture handle that the shader graph system can use
                TextureHandle textureToRead = renderGraph.ImportTexture(rtHandle);

                // Add the texture to the pass data
                passData.textureToRead = textureToRead;

                // Set the texture as readable
                builder.UseTexture(passData.textureToRead, AccessFlags.Read);

                builder.AllowPassCulling(false);

                builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));
            }
        }

        static void ExecutePass(PassData data, RasterGraphContext context)
        {          
            // Copy the imported texture to the render target
            Blitter.BlitTexture(context.cmd, data.textureToRead, new Vector4(0.8f,0.6f,0,0), 0, false);
        }
    }
}

URP의 렌더 패스에서 텍스처 사용

렌더 그래프 시스템 API를 사용하여 텍스처를 커스텀 렌더 패스의 입력 또는 출력으로 설정하여 텍스처를 읽거나 쓸 수 있습니다.

렌더 패스에서 동일한 텍스처에서 읽기와 쓰기를 모두 수행할 수 없습니다. 자세한 내용은 렌더 패스 중 렌더 타깃 변경을 참조하십시오.

텍스처를 입력으로 설정

텍스처를 커스텀 렌더 패스의 입력으로 설정하려면 다음 단계를 따르세요:

1. RecordRenderGraph 메서드에서 패스가 사용하는 데이터에 텍스처 핸들 필드를 추가합니다.

예제:

// Create the data your pass uses
public class MyPassData
{
    // Add a texture handle
    public TextureHandle textureToUse;
}

2. 텍스처 핸들을 사용하려는 텍스처로 설정합니다.

예제:

// Add the texture handle to the data
RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
TextureHandle textureHandle = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);
passData.textureToUse = textureHandle;

3. 텍스처를 입력으로 설정하려면 UseTexture 메서드를 호출합니다.
예제:

builder.UseTexture(passData.textureToUse, AccessFlags.Read);

이제 SetRenderFunc 메서드에서 전달 데이터의 TextureHandle 오브젝트를 Blitter.BlitTexture와 같은 API의 입력으로 사용할 수 있습니다.

텍스처를 렌더링 타깃으로 설정

Blit과 같은 명령의 출력으로 텍스처를 설정하려면 RecordRenderGraph 메서드에서 SetRenderAttachment 메서드를 사용합니다. SetRenderAttachment 메서드는 기본적으로 텍스처를 쓰기 전용으로 설정합니다.

예를 들어 다음 명령은 임시 텍스처를 생성하고 이를 렌더 패스의 렌더링 타깃으로 설정합니다:

// Create texture properties
RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);

// Create the texture
TextureHandle targetTexture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);

// Set the texture as the render target
// The second parameter is the index the shader uses to access the texture
builder.SetRenderAttachment(targetTexture, 0);

이제 SetRenderFunc 메서드에서 Blitter.BlitTexture와 같은 API를 사용하여 텍스처에 쓸 수 있습니다.

패스 데이터에 텍스처를 추가할 필요가 없습니다. 렌더 그래프 시스템은 렌더 패스를 실행하기 전에 텍스처를 자동으로 설정합니다.

렌더 대상에 오브젝트를 그려야 하는 경우 렌더 패스에 오브젝트 그리기를 참조하여 자세한 정보를 확인하세요.

 

렌더링 패스 중 렌더링 타깃 변경하기

렌더 그래프 시스템 렌더 패스 중에는 URP가 어떤 텍스처에 쓰는지 변경할 수 없습니다.

대신 다음 중 하나를 수행할 수 있습니다:

  • 두 번째 커스텀 렌더 패스를 생성하고 두 번째 렌더 패스 중에 builder.SetRenderAttachment를 사용하여 렌더 타깃을 변경합니다.
  • UnsafePass API를 사용하면 SetRenderFunc 메서드에서 SetRenderTarget API를 사용할 수 있습니다.자세한 내용과 예제는 그래프 렌더링 패스에서 호환 모드 API 사용을 참조하세요.

이러한 방법을 사용하면 먼저 텍스처에서 생성한 임시 텍스처로 복사한 다음 다시 복사하여 동일한 텍스처에서 읽고 쓸 수 있습니다.

속성이 다른 여러 텍스처 사이에
를 blit 하는 경우 URP가 블릿을 하나의 기본 렌더 패스로 병합할 수 없기 때문에 렌더링 속도가 느려질 수 있습니다. 대신 AddUnSafePass API와 SetRenderTarget() 메서드를 사용하세요.

예제

다음을 참조하세요:

 

Unity - Manual: Write a render pass using the render graph system in URP

Introduction to the render graph system in URP Textures in the Render Graph system in URP Write a render pass using the render graph system in URP This page describes how to write a render pass using the render graph system. To illustrate the description,

docs.unity3d.com

 

 

Unity - Manual: Import a texture into the render graph system in URP

Create a texture in the render graph system in URP Use a texture in a render pass in URP Import a texture into the render graph system in URP When you create a texture in the render graph system in a render pass, the render graph system handles the creatio

docs.unity3d.com

URP에서 렌더 패스 간 텍스처 전송

예를 들어 한 렌더 패스에서 텍스처를 생성하고 이후 렌더 패스에서 읽어야 하는 경우 렌더 패스 간에 텍스처를 전송할 수 있습니다.

다음 방법을 사용하여 렌더 패스 간에 텍스처를 전송할 수 있습니다:

 

Unity - Manual: Transfer a texture between render passes in URP

Use a texture in a render pass in URP Best practice for blitting in URP Transfer a texture between render passes in URP You can transfer a texture between render passes, for example if you need to create a texture in one render pass and read it in a later

docs.unity3d.com

 

 

Unity - Manual: Transfer a texture between render passes in URP

Use a texture in a render pass in URP Best practice for blitting in URP Transfer a texture between render passes in URP You can transfer a texture between render passes, for example if you need to create a texture in one render pass and read it in a later

docs.unity3d.com

텍스처를 렌더 패스 외부에 저장할 수도 있습니다. 예를 들어 스크립터블 렌더러 기능의 TextureHandle로 저장할 수 있습니다.

텍스처를 여러 프레임에서 사용할 수 있는지 확인하거나 여러 카메라
에서 텍스처에 액세스할 수 있도록 해야 하는 경우, 대신 렌더 그래프 시스템으로 텍스처 가져오기를 참조하세요.

 

프레임 데이터에 텍스처 추가

프레임 데이터에 텍스처를 추가하여 나중에 렌더링 패스에서 텍스처를 가져올 수 있습니다.

다음 단계를 따르세요:

1. ContextItem을 상속하고 텍스처 핸들 필드를 포함하는 클래스를 만듭니다.

예제:

public class MyCustomData : ContextItem {
    public TextureHandle textureToTransfer;
}

2. 프레임이 리셋될 때 텍스처를 리셋하려면 클래스에서 Reset() 메서드를 구현해야 합니다.
예제:

public class MyCustomData : ContextItem {
    public TextureHandle textureToTransfer;

    public override void Reset()
    {
        textureToTransfer = TextureHandle.nullHandle;
    }
}

3. 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>();
    }
}

4. 텍스처 핸들을 텍스처로 설정합니다.
예제:

// 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 클래스를 추가합니다. 첫 번째 렌더 패스는 텍스처를 노란색으로 지우고, 두 번째 렌더 패스는 노란색 텍스처를 가져와서 그 위에 삼각형을 그립니다.

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);
}

아직 세트렌더펀크호출하지 않았다면 빈 렌더링 함수도 추가해야 합니다. 예를 들어

builder.SetRenderFunc((PassData data, RasterGraphContext context) => { });

이제 가능합니다:

  • 다른 렌더링 패스의 텍스처에 액세스하려면 UseGlobalTexture() 또는 UseAllGlobalTextures() API를 사용합니다.
  • 씬의 모든 머티리얼에 텍스처를 사용합니다.

URP에서 블리팅을 위한 모범 사례

Blit 작업은 소스 텍스처를 대상 텍스처로 복사하는 프로세스입니다.

이 페이지에서는 URP에서 blit 작업을 수행하는 다양한 방법과 커스텀 렌더 패스를 작성할 때 따라야 할 모범 사례에 대한 개요를 제공합니다.

레거시 CommandBuffer.Blit API

URP 프로젝트에서 CommandBuffer.Blit API를 사용하지 마세요.

CommandBuffer.Blit API는 레거시 API입니다. 상태 변경, 텍스처 바인딩, 렌더 타깃 설정과 관련된 추가 작업을 암시적으로 실행합니다. 이러한 작업은 SRP 프로젝트에서 내부적으로 이루어지며 사용자에게 투명하지 않습니다.

이 API는 URP XR
통합과 호환성 문제가 있습니다. cmd.Blit을 사용하면 XR 셰이더
키워드를 암시적으로 활성화 또는 비활성화할 수 있으며, 이로 인해 XR SPI 렌더링이 중단될 수 있습니다.

CommandBuffer.Blit API는 NativeRenderPass 및 RenderGraph와 호환되지 않습니다.

내부적으로 cmd.Blit에 의존하는 모든 유틸리티 또는 래퍼에도 비슷한 고려 사항이 적용되며, RenderingUtils.Blit이 그러한 예 중 하나입니다.

SRP Blitter API

URP 프로젝트에서 Blitter API를 사용하세요. 이 API는 레거시 로직에 의존하지 않으며 XR, 네이티브 렌더 패스 및 기타 SRP API와 호환됩니다.

사용자 지정 전체 화면 블릿 예시

호환 모드의 URP에서 전체 화면 블릿을 수행하는 방법 예제에서는 전체 화면 블릿을 수행하는 커스텀 렌더러 기능을 만드는 방법을 보여줍니다. 이 예제는 XR에서 작동하며 SRP API와 호환됩니다.

 

URP의 렌더 그래프 시스템의 프레임 데이터

유니버설 렌더 파이프라인(URP)이 현재 프레임 또는 이전 프레임에 대해 생성하는 텍스처(예: 컬러 텍스처 또는 뎁스 텍스처)를 가져옵니다.

 

Page 설명

Get data from the current frame URP가 현재 프레임에 대해 생성하는 텍스처를 가져옵니다.
Get data from previous frames 카메라에서 렌더링한 이전 프레임을 가져오려면 UniversalCameraData.historyManager API를 사용합니다.
Add textures to previous frames 카메라 히스토리에 나만의 텍스처를 추가하려면 카메라 히스토리 유형을 만들어 프레임 사이에 텍스처를 저장하세요.
Get the current framebuffer with framebuffer fetch 렌더링 속도를 높이려면 프레임버퍼 페치를 사용하여 Unity가 지금까지 렌더링한 프레임을 읽습니다.
Frame data textures reference 현재 프레임 또는 이전 프레임에서 가져올 수 있는 텍스처를 살펴보세요.

URP의 현재 프레임에서 데이터 가져오기

유니버설 렌더 파이프라인(URP)이 현재 프레임에 대해 생성하는 텍스처(예: 활성 컬러 버퍼 또는 G 버퍼 텍스처)를 가져와서 렌더 패스에 사용할 수 있습니다.

이러한 텍스처를 프레임 데이터, 리소스 데이터 또는 프레임 리소스라고 합니다. 이 문서에서는 이러한 텍스처를 프레임 데이터라고 합니다.

사용자 지정 렌더 패스를 URP 프레임 렌더링 루프에 삽입하는 데 사용하는 주입 지점에 따라 일부 텍스처가 프레임 데이터에 존재하지 않을 수 있습니다. 어떤 텍스처가 언제 존재하는지에 대한 자세한 내용은 주입 지점 참조를 참조하십시오.

프레임 데이터 가져오기

프레임 데이터는 레코드 렌더 그래프 메서드를 오버라이드할 때 URP가 제공하는 컨텍스트 컨테이너 오브젝트에 있습니다.

 

프레임 데이터에서 텍스처에 대한 핸들을 얻으려면 다음 단계를 따르세요:

1. ContextContainer 객체의 Get 메서드를 사용하여 모든 프레임 데이터를 UniversalResourceData 객체로 가져옵니다.

예시:

public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
    using (var builder = renderGraph.AddRasterRenderPass<PassData>("Get frame data", out var passData))
    {
        UniversalResourceData frameData = frameContext.Get<UniversalResourceData>();
    }
}

2. 프레임 데이터에서 텍스처에 대한 핸들을 가져옵니다.

예를 들어 다음은 활성 색상 텍스처에 대한 핸들을 가져옵니다:

```csharp
TextureHandle activeColorTexture = frameData.activeColorTexture;
```

그런 다음 텍스처에서 읽고 쓸 수 있습니다. 렌더 패스에서 텍스처 사용을 참조하십시오.

텍스처 핸들은 현재 프레임의 현재 렌더 그래프에만 유효합니다.

구성 입력 API를 사용하여 URP가 프레임 데이터에 필요한 텍스처를 생성하는지 확인할 수 있습니다.

예제

전체 예제는 유니버설 렌더 파이프라인(URP) 패키지 샘플에서 TextureReference w. FrameData라는 예제를 참조하세요.

URP의 이전 프레임에서 데이터 가져오기

유니버설 렌더 파이프라인(URP)에서 카메라가 렌더링한 이전 프레임을 가져오려면 UniversalCameraData.historyManager API를 사용합니다.
이러한 텍스처를 히스토리 텍스처 또는 히스토리 버퍼라고 부르기도 합니다.

프레임은 GPU 렌더링 파이프라인의 출력이므로 포스트 프로세싱 효과와 같은 GPU 렌더링 이후에 발생하는 처리는 포함되지 않습니다.

스크립트 가능한 렌더 패스 외부에서 이전 프레임을 가져오려면 스크립트에서 이전 프레임에서 데이터 가져오기를 참조하세요.

다음 단계를 따르세요:

1. RecordRenderGraph 메서드에서 컨텍스트 컨테이너 객체에서 유니버설 카메라 데이터 객체를 가져옵니다.

예)

public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
    UniversalCameraData cameraData = frameContext.Get<UniversalCameraData>();
}


2. 렌더링 기록에서 컬러 텍스처 또는 뎁스 텍스처에 대한 액세스를 요청하려면 RequestAccess API를 사용하세요 .
예)

// Request access to the color textures
cameraData.historyManager.RequestAccess<RawColorHistory>();

 뎁스 텍스처에 대한 액세스를 요청하려면 대신 RawDepthHistory를 사용합니다 .

3. 이전 텍스처 중 하나를 가져옵니다.
예)

// Get the previous textures 
RawColorHistory history = cameraData.historyManager.GetHistoryForRead<RawColorHistory>();

// Get the first texture, which the camera rendered in the previous frame
RTHandle historyTexture = history?.GetPreviousTexture(0);

4. 텍스처를 렌더 그래프 시스템이 사용할 수 있는 핸들로 변환합니다.
예)

passData.historyTexture = renderGraph.ImportTexture(historyTexture);

그런 다음 렌더 패스에서 텍스처를 읽을 수 있습니다.

historyManager API 사용에 대한 자세한 내용은 UniversalCameraData.historyManager를 참조하세요.

예제

다음은 머티리얼을 생성하고 이전 프레임을 머티리얼의 텍스처로 사용하는 스크립터블 렌더러 기능입니다.

이 예제를 사용하려면 다음 단계를 따르세요:

  1. BaseMap이라는 텍스처를 샘플링하는 URP 셰이더를 만듭니다. 예제는 텍스처 그리기를 참조하세요.
  2. 셰이더에서 머티리얼을 만듭니다.
  3. RenderLastFrameInMaterial.cs라는 새 C# 스크립트를 만들고 다음 코드를 붙여넣고 파일을 저장합니다.
  4. 활성 URP 렌더러에서 스크립터블 렌더러 기능을 추가합니다.
  5. 활성 URP 렌더러의 인스펙터 창에서 4단계에서 추가한 스크립터블 렌더러 기능의 마지막 프레임 렌더링 머티리얼 섹션에서 2단계에서 생성한 머티리얼을 오브젝트 머티리얼 필드에 할당합니다.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
public class RenderLastFrameInMaterial : ScriptableRendererFeature
{
    public Material objectMaterial;
    CustomRenderPass renderLastFrame;

    public override void Create()
    {
        renderLastFrame = new CustomRenderPass();
        renderLastFrame.renderPassEvent = RenderPassEvent.BeforeRenderingOpaques;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderLastFrame.passMaterial = objectMaterial;
        renderer.EnqueuePass(renderLastFrame);
    }

    class CustomRenderPass : ScriptableRenderPass
    {
        public Material passMaterial;

        public class PassData
        {
            internal Material material;
            internal TextureHandle historyTexture;
        }

        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer contextData)
        {
            UniversalCameraData cameraData = contextData.Get<UniversalCameraData>();

            // Return if the history manager isn't available
            // For example, there are no history textures during the first frame
            if (cameraData.historyManager == null) { return; }
  
            // Request access to the color and depth textures
            cameraData.historyManager.RequestAccess<RawColorHistory>();

            using (var builder = renderGraph.AddRasterRenderPass<PassData>("Get last frame", out var passData))
            {
                UniversalResourceData resourceData = contextData.Get<UniversalResourceData>();

                // Set the render graph to render to the active color texture
                builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write);

                // Add the material to the pass data
                passData.material = passMaterial;
                
                // Get the color texture the camera rendered to in the previous frame
                RawColorHistory history = cameraData.historyManager.GetHistoryForRead<RawColorHistory>();
                RTHandle historyTexture = history?.GetPreviousTexture(0);
                passData.historyTexture = renderGraph.ImportTexture(historyTexture);

                builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
                {
                    // Set the material to use the texture
                    data.material.SetTexture("_BaseMap", data.historyTexture);
                });
            }
        }
    }
}

스크립트에서 이전 프레임의 데이터 가져오기

스크립트에서 이전 프레임(예: 모노비헤이비어)의 데이터를 가져오려면 다음과 같이 하세요:

  1. 스크립터블 렌더 파이프라인(SRP) 코어 RequestAccess API를 사용하여 텍스처를 요청합니다.
  2. UniversalAdditionalCameraData.history API를 사용하여 데이터를 가져옵니다.

Unity가 프레임 렌더링을 먼저 완료하도록 하려면 LateUpdate 메서드에서 UniversalAdditionalCameraData.history API를 사용합니다.

자세한 내용은 스크립터블 렌더 파이프라인(SRP) 코어 패키지에서 다음을 참조하세요:

 

 

Interface ICameraHistoryReadAccess | Core RP Library | 17.0.3

Interface ICameraHistoryReadAccess User API to get history read access for a user history type instance. Read access is valid and available after the history type has been requested and written by a render pass. Otherwise a null is returned. Typically call

docs.unity3d.com

 

 

Interface IPerFrameHistoryAccessTracker | Core RP Library | 17.0.3

Interface IPerFrameHistoryAccessTracker User API to request access for an instance of the user history type. Tracks the history types that were requested by the render pipeline features on this frame. Requested history types are then made available for the

docs.unity3d.com

URP에서 이전 프레임에 데이터 추가

카메라 히스토리에 자신만의 텍스처를 추가하고 이후 프레임에서 데이터를 읽으려면 카메라 히스토리 유형을 만들어 프레임 사이에 텍스처를 저장하세요.

카메라 기록 유형 만들기

다음 단계를 따르세요:

1. CameraHistoryItem을 상속하는 클래스를 생성합니다.
예):

public class ExampleHistoryType : CameraHistoryItem {
    ...
}

2. 클래스에서 카메라 기록 시스템의 ID를 추가합니다. 예)

private int uniqueId;

 

프레임 사이에 저장해야 하는 텍스처 설명자 등 필요한 다른 데이터도 추가할 수 있습니다(예: 텍스처 설명자).

3. Override the OnCreate method. In the method, call the OnCreate method of the parent class, and generate the unique 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);
}

4. 현재 및 이전 텍스처에 대한 공용 프로퍼티를 생성하여 렌더 패스가 액세스할 수 있도록 합니다.
예)

public RTHandle currentTexture => GetCurrentFrameRT(uniqueId);
public RTHandle previousTexture => GetPreviousFrameRT(uniqueId);

5. 텍스처에 메모리를 할당합니다.
예)

// Allocate 2 textures using a texture descriptor, assign them to the uniqueId, and give them a name.
AllocHistoryFrameRT(uniqueId, 2, ref textureDescriptor, "ExampleHistoryTexture");

렌더 패스가 다른 크기나 형식의 텍스처를 작성하는 경우 매 프레임마다 메모리를 재할당해야 할 수도 있습니다.

텍스처에 쓰기

생성한 텍스처에 쓰려면 다음 단계를 따르세요:
1. 스크립터블 렌더패스 클래스에서 텍스처에 대한 액세스를 요청하려면 카메라 히스토리 유형과 함께 RequestAccess API를 사용하세요.
예)

cameraData.historyManager.RequestAccess<ExampleHistoryType>();

2. 현재 프레임의 텍스처를 가져와서 렌더 그래프 시스템이 사용할 수 있는 핸들로 변환합니다.
예)

// Get the textures 
RawColorHistory 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);
                });
            }
        }
    }
}

URP에서 프레임버퍼 가져오기를 통해 현재 프레임버퍼 가져오기

렌더링 속도를 높이려면 프레임버퍼 페치를 사용하여 Unity가 지금까지 렌더링한 프레임을 읽습니다.

프레임버퍼 페치를 사용하면 렌더 패스가 비디오 메모리 대신 GPU의 온칩 메모리에서 프레임버퍼에 액세스할 수 있습니다. 이렇게 하면 GPU가 텍스처를 비디오 메모리로 복사할 필요가 없으므로 렌더링 속도가 빨라집니다.

프레임버퍼 가져오기는 다음 그래픽 API 중 하나를 사용하는 경우 지원됩니다:

  • Vulkan
  • Metal

프레임버퍼 가져오기는 타일 기반 지연 렌더링(TBDR)을 사용하는 모바일 디바이스에서 렌더링 속도를 크게 높여줍니다. GPU는 렌더링 패스 사이에 온칩 타일 메모리에 프레임을 유지하므로 메모리 대역폭과 처리 시간을 덜 사용합니다.

프레임버퍼 가져오기를 사용하는 경우 URP는 프레임버퍼에 쓰고 프레임버퍼에서 읽는 렌더 패스를 병합합니다. 렌더 그래프 뷰어 창에서 이를 확인할 수 있습니다.

프레임 버퍼 패치 사용

렌더 패스에서 프레임버퍼 가져오기를 사용하려면 다음을 사용합니다:

  • 이전 렌더링 패스의 출력을 새 렌더링 패스의 입력으로 설정하는 SetInputAttachment API입니다.
  • 프래그먼트 셰이더 코드의 LOAD_FRAMEBUFFER_X_INPUT 매크로를 사용하여 이전 렌더링 패스의 출력을 샘플링하는 대신 SAMPLE_TEXTURE2D와 같은 매크로를 사용할 수 있습니다.

다음 단계에서는 sourceTextureHandle이라는 TextureHandle에 쓰는 렌더 패스가 이미 하나 있다고 가정합니다.

  1. 사용자 정의 셰이더를 만든 다음 셰이더에서 머티리얼을 만듭니다. 사용자 정의 셰이더를 만드는 방법에 대한 자세한 내용은 사용자 정의 셰이더 작성을 참조하십시오.
  2. 커스텀 셰이더의 HLSLPROGRAM에서 Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl 파일을 임포트해야 합니다:
HLSLPROGRAM
...
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
...
ENDHLSL

3. HLSLPROGRAM 내에서 다음 중 하나를 사용하여 이전 렌더링 패스의 텍스처를 선언합니다. 
예)

  • FRAMEBUFFER_INPUT_X_HALF
  • FRAMEBUFFER_INPUT_X_FLOAT
  • FRAMEBUFFER_INPUT_X_INT
  • FRAMEBUFFER_INPUT_X_UINT

예)  

FRAMEBUFFER_INPUT_X_HALF(0);

4. 프래그먼트 함수에서 프레임버퍼 가져오기를 사용하여 텍스처를 샘플링하려면 LOAD_FRAMEBUFFER_X_INPUT 을 사용합니다 .

예를 들어

half4 frag() : SV_Target
{
    half4 colorFromPreviousRenderPass = LOAD_FRAMEBUFFER_X_INPUT(0, input.positionCS.xy);
    return colorFromPreviousRenderPass;
}

5. 새 렌더 그래프 렌더 패스에서 생성한 머티리얼을 패스데이터에 추가합니다 .
예)

class PassData
{
    public Material frameBufferFetchMaterial;
}

6. builder.SetInputAttachment를 사용하여 이전 렌더링 패스의 출력을 새 렌더링 패스의 입력으로 설정합니다.
예)

builder.SetInputAttachment(sourceTextureHandle, 0, AccessFlags.Read);

7. SetRenderFunc 메서드에서 BlitTexture 와 같은 명령을 사용하여 머티리얼을 사용하여 렌더링합니다.
예)

static void ExecutePass(PassData data, RasterGraphContext context)
{
    Blitter.BlitTexture(context.cmd, new Vector4(1, 1, 0, 0), frameBufferFetchMaterial, 1);
}

예제

전체 예제는 렌더 그래프 시스템 URP 패키지 샘플에서 FrameBufferFetch라는 예제를 참조하세요.

 

URP용 프레임 데이터 텍스처 레퍼런스

프레임 데이터에서 다음 텍스처를 가져올 수 있습니다.

PropertyTextureURP 셰이더
 텍스처에 쓰는 패스

additionalShadowsTexture  The additional shadow map. ShadowCaster
activeColorTexture The color texture the camera
 currently targets.
Any pass, depending on your settings
activeDepthTexture The depth texture the camera is currently targets. Any pass, depending on your settings
afterPostProcessColor The main color texture after URP’s post processing passes. UberPost
backBufferColor  The color texture of the screen back buffer. If you use post-processing
, URP writes to this texture at the end of rendering, unless you enable HDR Debug Views. Refer to debugScreenTexture for more information.
Any pass, depending on your settings
backBufferDepth  The depth texture of the screen back buffer. Any pass, depending on your settings
cameraColor The main color texture for the camera. You can store multiple samples in this texture if you enable Multisample Anti-aliasing (MSAA). Any pass, depending on your settings
cameraDepth The main depth texture for the camera. You can store multiple samples in this texture if you enable Multisample Anti-aliasing (MSAA). Any pass, depending on your settings
cameraDepthTexture A copy of the depth texture, if you enable Depth Priming Mode in the renderer or Depth Texture in the active URP Asset. CopyDepth or DepthPrepass
cameraNormalsTexture The scene
 normals texture. Contains the scene depth for objects with shaders that have a DepthNormals pass.
DepthNormals prepass
cameraOpaqueTexture A texture with the opaque objects in the scene, if you enable Opaque Texture in the URP Asset. CopyColor
dBuffer The Decals texture. For more information about the decals texture, refer to DBuffer. Decals
dBufferDepth The Decals depth texture. Refer to DBuffer. Decals
debugScreenTexture If you enable HDR Debug Views, URP writes the output of post-processing to this texture instead of backBufferColor. uberPost and finalPost
gBuffer The G-buffer textures. Refer to G-buffer. GBuffer
internalColorLut The internal look-up textures (LUT) texture. InternalLut
mainShadowsTexture  The main shadow map. ShadowCaster
motionVectorColor The motion vectors color texture. Refer to motion vectors. Camera Motion Vectors and MotionVectors
motionVectorDepth The motion vectors depth texture. Refer to motion vectors. Camera Motion Vectors and MotionVectors
overlayUITexture The overlay UI
 texture.
DrawScreenSpaceUI
renderingLayersTexture The Rendering Layers texture. Refer to Rendering layers DrawOpaques or the DepthNormals prepass, depending on your settings.
ssaoTexture The Screen Space Ambient Occlusion (SSAO) texture. Refer to Ambient occlusion
.
SSAO

 

URP의 렌더 그래프 시스템에서 오브젝트 그리기

렌더 그래프 시스템을 사용하는 커스텀 렌더 패스에서 오브젝트를 그리려면 렌더러리스트 핸들 API를 사용하여 그릴 오브젝트 목록을 생성합니다.

그릴 개체 목록 만들기

다음 단계를 따르세요:

1. 스크립터블 렌더패스 클래스의 전달 데이터에 사용하는 클래스에서 RendererListHandle 필드를 만듭니다.
예)

private class PassData
{
    public RendererListHandle objectsToDraw;
}

2. 그릴 오브젝트, 그리기 설정 및 컬링 데이터를 포함하는 RendererListParams 오브젝트를 만듭니다. RenderListParams 오브젝트에 대한 자세한 내용은 커스텀 렌더 파이프라인에서 간단한 렌더 루프 만들기를 참조하고, 자세한 예제는 예제를 참조하세요.

3. RecordRenderGraph 메서드에서 CreateRendererList API를 사용하여 렌더러 목록 개체를 렌더 그래프 시스템에서 사용할 수 있는 핸들로 변환합니다.
예)

RenderListHandle rendererListHandle = renderGraph.CreateRendererList(rendererListParameters);

4. 패스 데이터에서 RendererListHandle 필드를 설정합니다.
예)

passData.objectsToDraw = rendererListHandle;

개체 그리기

전달 데이터에 렌더러리스트 핸들을 설정한 후 목록에 있는 오브젝트를 그릴 수 있습니다.

다음 단계를 따르세요:

1. RecordRenderGraph 메서드에서 UseRendererList API를 사용하여 렌더 그래프 시스템에 오브젝트 목록을 사용하도록 지시합니다.
예)

builder.UseRendererList(passData.rendererListHandle);

2. 개체를 그릴 텍스처를 설정합니다. 색상 텍스처와 깊이 텍스처를 모두 설정하여 URP가 오브젝트를 올바르게 렌더링하도록 합니다.
예를 들어 다음은 URP가 활성 카메라 텍스처의 컬러 텍스처와 뎁스 텍스처에 그리도록 지시합니다.

UniversalResourceData frameData = frameContext.Get<UniversalResourceData>();
builder.SetRenderAttachment(frameData.activeColorTexture, 0);
builder.SetRenderAttachmentDepth(frameData.activeDepthTexture, AccessFlags.Write);

SetRenderFunc 메서드에서 DrawRendererList API를 사용하여 렌더러를 그립니다.
예)

context.cmd.DrawRendererList(passData.rendererListHandle);

예제

다음 스크립터블 렌더러 기능은 씬의 오브젝트에서 라이트모드 태그가 유니버설포워드로 설정된 오브젝트를 오버라이드 머티리얼을 사용하여 다시 그립니다.

이 스크립터블 리더 기능을 렌더러에 추가한Material To Use 파라미터를 모든 머티리얼로 설정합니다.

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
 
public class DrawObjectsWithOverrideMaterial : ScriptableRendererFeature
{

    DrawObjectsPass drawObjectsPass;
    public Material overrideMaterial;
 
    public override void Create()
    {
        // Create the render pass that draws the objects, and pass in the override material
        drawObjectsPass = new DrawObjectsPass(overrideMaterial);

        // Insert render passes after URP's post-processing render pass
        drawObjectsPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }
 
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        // Add the render pass to the URP rendering loop
        renderer.EnqueuePass(drawObjectsPass);
    }

    class DrawObjectsPass : ScriptableRenderPass
    {
        private Material materialToUse;

        public DrawObjectsPass(Material overrideMaterial)
        {
            // Set the pass's local copy of the override material 
            materialToUse = overrideMaterial;
        }
       
        private class PassData
        {
            // Create a field to store the list of objects to draw
            public RendererListHandle rendererListHandle;
        }
 
        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
        {
            using (var builder = renderGraph.AddRasterRenderPass<PassData>("Redraw objects", out var passData))
            {
                // Get the data needed to create the list of objects to draw
                UniversalRenderingData renderingData = frameContext.Get<UniversalRenderingData>();
                UniversalCameraData cameraData = frameContext.Get<UniversalCameraData>();
                UniversalLightData lightData = frameContext.Get<UniversalLightData>();
                SortingCriteria sortFlags = cameraData.defaultOpaqueSortFlags;
                RenderQueueRange renderQueueRange = RenderQueueRange.opaque;
                FilteringSettings filterSettings = new FilteringSettings(renderQueueRange, ~0);

                // Redraw only objects that have their LightMode tag set to UniversalForward 
                ShaderTagId shadersToOverride = new ShaderTagId("UniversalForward");

                // Create drawing settings
                DrawingSettings drawSettings = RenderingUtils.CreateDrawingSettings(shadersToOverride, renderingData, cameraData, lightData, sortFlags);

                // Add the override material to the drawing settings
                drawSettings.overrideMaterial = materialToUse;

                // Create the list of objects to draw
                var rendererListParameters = new RendererListParams(renderingData.cullResults, drawSettings, filterSettings);

                // Convert the list to a list handle that the render graph system can use
                passData.rendererListHandle = renderGraph.CreateRendererList(rendererListParameters);
                
                // Set the render target as the color and depth textures of the active camera texture
                UniversalResourceData resourceData = frameContext.Get<UniversalResourceData>();
                builder.UseRendererList(passData.rendererListHandle);
                builder.SetRenderAttachment(resourceData.activeColorTexture, 0);
                builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write);

                builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));
            }
        }

        static void ExecutePass(PassData data, RasterGraphContext context)
        {
            // Clear the render target to black
            context.cmd.ClearRenderTarget(true, true, Color.black);

            // Draw the objects in the list
            context.cmd.DrawRendererList(data.rendererListHandle);
        }

    }
 
}

다른 예시는 렌더 그래프 시스템 URP 패키지 샘플의RendererList라는 예제를 참조하십시오

URP의 렌더 그래프 시스템에서 셰이더 계산하기

컴퓨트 셰이더를 실행하는 렌더 패스를 만들려면 렌더 그래프 시스템을 사용합니다.

페이지 설명

Run a compute shader in a render pass 버퍼를 할당하고 컴퓨팅 셰이더를 실행하여 데이터를 버퍼로 출력하는 렌더 패스를 생성합니다.
Create input data for a compute shader 렌더 패스에서 컴퓨팅 셰이더에 입력 데이터를 제공하는 버퍼를 할당합니다.

URP의 렌더 패스에서 컴퓨트 셰이더를 실행합니다.

컴퓨트 셰이더를 실행하는 렌더 패스를 만들려면 다음을 수행합니다:

  1. 컴퓨트 셰이더를 사용하도록 렌더 패스를 설정합니다.
  2. 출력 버퍼를 추가합니다.
  3. 계산 셰이더를 전달하고 실행합니다.
  4. 출력 버퍼에서 출력 데이터를 가져옵니다.

플랫폼이 컴퓨팅 셰이더를 지원하는지 확인하려면 SystemInfo.supportsComputeShaders API를 사용하세요.

컴퓨트 셰이더를 사용하도록 렌더 패스를 설정합니다.

스크립터블 렌더 패스를 생성할 때 다음을 수행합니다:

  1. AddRasterRenderPass 대신 AddComputePass를 사용합니다.
  2. RasterGraphContext 대신 ComputeGraphContext를 사용합니다.

예)

class ComputePass : ScriptableRenderPass
{
    ...

    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer contextData)
    {
        ...
        // Use AddComputePass instead of AddRasterRenderPass.
        using (var builder = renderGraph.AddComputePass("MyComputePass", out PassData data))
        {
            ...

            // Use ComputeGraphContext instead of RasterGraphContext.
            builder.SetRenderFunc((PassData data, ComputeGraphContext context) => ExecutePass(data, context));

            ...
        }
    }
}

output buffer 추가

컴퓨트 셰이더가 출력하는 버퍼를 만들려면 다음 단계를 따르세요:

1. 그래픽 버퍼를 생성한 다음 패스 데이터에 핸들을 추가합니다.

// Declare an output buffer
public GraphicsBuffer outputBuffer;

// Add a handle to the output buffer in your pass data
class PassData
{
    public BufferHandle output;
}

// Create the buffer in the render pass constructor
public ComputePass(ComputeShader computeShader)
{
    // Create the output buffer as a structured buffer
    // Create the buffer with a length of 5 integers, so the compute shader can output 5 values.
    outputBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 5, sizeof(int));
}

2. ImportBuffer 렌더 그래프 API를 사용하여 버퍼를 렌더 그래프 시스템에서 사용할 수 있는 핸들로 변환한 다음 전달 데이터에 BufferHandle 필드를 설정합니다.
예)

BufferHandle outputHandleRG = renderGraph.ImportBuffer(outputBuffer);
passData.output = outputHandleRG;

3. 사용 버퍼 메서드를사용하여 렌더 그래프 시스템에서 버퍼를 쓰기 가능한 버퍼로 설정합니다.

builder.UseBuffer(passData.output, AccessFlags.Write);

컴퓨트 셰이더를 전달하고 실행합니다.

Follow these steps:

1. 렌더 패스에 계산 셰이더를 전달합니다. 예를 들어 스크립터블 렌더러 피처 클래스에서 컴퓨트 셰이더 프로퍼티를 노출한 다음 컴퓨트 셰이더를 렌더 패스 클래스에 전달합니다.

2. 패스 데이터에 컴퓨트 셰이더 필드를 추가하고 이를 컴퓨트 셰이더로 설정합니다.
예)

// Add a `ComputeShader` field to your pass data
class PassData
{
    ...
    public ComputeShader computeShader;
}

// Set the `ComputeShader` field to the compute shader
passData.computeShader = yourComputeShader;

3. SetRenderFunc 메서드에서 SetComputeBufferParam API를 사용하여 버퍼를 계산 셰이더에 연결합니다.
 예)

// The first parameter is the compute shader
// The second parameter is the function that uses the buffer
// The third parameter is the StructuredBuffer output variable to attach the buffer to
// The fourth parameter is the handle to the output buffer
context.cmd.SetComputeBufferParam(passData.computeShader, passData.computeShader.FindKernel("Main"), "outputData", passData.output);

4. 계산 셰이더를 실행하려면DispatchCompute API를사용합니다 .

context.cmd.DispatchCompute(passData.computeShader, passData.computeShader.FindKernel("CSMain"), 1, 1, 1);

output data from the output buffer 취하기

출력 버퍼에서 데이터를 가져오려면 GraphicsBuffer.GetData API를 사용합니다.

렌더 패스가 실행되고 계산 셰이더 실행이 완료된 후에만 데이터를 가져올 수 있습니다.
예)

// Create an array to store the output data
outputData = new int[5];

// Copy the output data from the output buffer to the array
outputBuffer.GetData(outputData);

Create input data for a compute shader in URP

렌더 패스에서 컴퓨트 셰이더를 실행할 때 버퍼를 할당하여 컴퓨트 셰이더에 입력 데이터를 제공할 수 있습니다.

이 단계를 따르십시오.

1. 그래픽 버퍼를 생성한 다음 패스 데이터에 핸들을 추가합니다. 
예)

// Declare an input buffer
public GraphicsBuffer inputBuffer;

// Add a handle to the input buffer in your pass data
class PassData
{
    ...
    public BufferHandle input;
}

// Create the buffer in the render pass constructor
public ComputePass(ComputeShader computeShader)
{
    // Create the input buffer as a structured buffer
    // Create the buffer with a length of 5 integers, so you can input 5 values.
    inputBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 5, sizeof(int));
}

2. 버퍼에 데이터를 설정합니다.
예)

var inputValues = new List<int> { 1, 2, 3, 4, 5 };
inputBuffer.SetData(inputValues);

3. ImportBuffer 렌더 그래프 API를 사용하여 버퍼를 렌더 그래프 시스템에서 사용할 수 있는 핸들로 변환한 다음 전달 데이터에 BufferHandle 필드를 설정합니다
예)

BufferHandle inputHandleRG = renderGraph.ImportBuffer(inputBuffer);
passData.input = inputHandleRG;

4. UseBuffer 메서드를사용하여 렌더 그래프 시스템에서 버퍼를 읽기 가능한 버퍼로 설정합니다.
예)

builder.UseBuffer(passData.input, AccessFlags.Read);

5. SetRenderFunc 메서드에서 SetComputeBufferParam API를 사용하여 버퍼를 계산 셰이더에 연결합니다. 
예)

// The first parameter is the compute shader
// The second parameter is the function that uses the buffer
// The third parameter is the RWStructuredBuffer input variable to attach the buffer to
// The fourth parameter is the handle to the input buffer
context.cmd.SetComputeBufferParam(passData.computeShader, passData.computeShader.FindKernel("Main"), "inputData", passData.input);

 

URP에서 렌더 그래프 분석하기

렌더 그래프를 분석하는 방법에는 여러 가지가 있습니다:

  • 렌더 그래프 뷰어 사용
  • 렌더링 디버거 사용
  • 프레임 디버거 사용

Render Graph Viewer 사용

Render Graph Viewer window, go to Window > Analysis > Render Graph Viewer 을 엽니다.

렌더 그래프 뷰어 창에는 유니버설 렌더 파이프라인(URP) 단계별 최적화된 렌더 패스 시퀀스인 렌더 그래프가 각 프레임에 표시됩니다. 렌더 그래프 뷰어에는 기본 제공 렌더 패스와 사용자가 생성한 커스텀 렌더 패스가 모두 표시됩니다.

렌더 그래프 뷰어 창에 대한 자세한 내용은 렌더 그래프 뷰어 창 참조를 참조하세요.

렌더링 그래프 보기

렌더 그래프 뷰어 창에는 기본적으로 현재 씬의 렌더 그래프가 표시됩니다. 다른 렌더 그래프를 선택하려면 툴바의 드롭다운을 사용합니다.

예: URP가 리소스를 사용하는 방법 확인

리소스 이름 옆의 리소스 액세스 블록을 사용하여 렌더 패스가 리소스를 사용하는 방식을 확인할 수 있습니다.

렌더 그래프 뷰어 예제

이전 예제에서 _MainLightShadowmapTexture_ 텍스처는 다음 단계를 거칩니다:

  1. InitFrame과 SetupCameraProperties 사이의 처음 5번의 렌더링 패스 동안 텍스처는 존재하지 않습니다.
  2. 메인 라이트 섀도맵 렌더 패스는 텍스처를 글로벌 텍스처로 생성하며, 쓰기 전용 액세스 권한을 가집니다.글로벌 텍스처에 대한 자세한 내용은 패스 간 텍스처 전송을 참조하십시오.
  3. 메인 라이트 섀도맵 아래의 파란색 병합 막대는 URP가 메인 라이트 섀도맵, 추가 라이트 섀도맵SetupCameraProperties를 단일 렌더 패스로 병합했음을 의미합니다.
  4. 다음 5번의 렌더 패스는 텍스처에 액세스할 수 없습니다.
  5. 첫 번째 오브젝트 그리기 렌더 패스는 텍스처에 대한 읽기 전용 액세스 권한을 가집니다.
  6. 다음 두 렌더 패스는 텍스처에 액세스할 수 없습니다.
  7. 두 번째 오브젝트 그리기 렌더 패스는 텍스처에 대한 읽기 전용 액세스 권한을 가집니다.
  8. 텍스처는 더 이상 필요하지 않으므로 Unity에서 삭제합니다.

URP가 렌더 패스를 최적화한 방법 확인

렌더 패스의 세부 정보를 확인하려면(예: 네이티브 렌더 패스 또는 병합 패스가 아닌 이유를 확인하려면) 다음 중 하나를 수행합니다:

  • 렌더링 패스 이름을 선택하여 패스 목록에 세부 정보를 표시합니다.
  • 렌더 패스 이름 아래에서 회색, 파란색 또는 깜박이는 파란색 리소스 액세스 개요 블록 위로 커서를 가져갑니다.

렌더 패스 세부 정보 표시에 대한 자세한 내용은 렌더 그래프 뷰어 창 참조를 참조하세요.

 

렌더링 디버거 사용

렌더링 디버거를 사용하여 콘솔 창에서 URP가 사용하는 리소스와 그 사용 방법을 기록할 수 있습니다.

로깅을 사용 설정하려면 다음 단계를 따르세요:

  1. 창 > 분석 > 렌더링 디버거를 선택하여 렌더링 디버거 창을 엽니다.
  2. 왼쪽 창에서 그래프 렌더링 탭을 선택합니다.
  3. 로깅 사용을 활성화합니다.
  4. 프레임 정보 로그를 선택하여 URP가 리소스를 사용하는 방법을 기록하거나 리소스 로그를 선택하여 리소스에 대한 세부 정보를 기록합니다.
  5. 콘솔 창에서 새 항목을 선택하면 전체 로그가 표시됩니다.

렌더링 디버거에 대한 자세한 내용은 렌더링 디버거를 참조하세요.

 

프레임 디버거 사용

프레임 디버거를 사용하여 렌더링 루프에서 렌더링 패스와 드로우 호출을 확인합니다.

렌더 그래프 시스템이 활성화되면 프레임 디버거는 이벤트 계층구조 패널에 다음을 표시합니다:

  • 부모 렌더링 이벤트는 ExecuteRenderGraph입니다.
  • 하위 렌더링 이벤트는 (RP <render-pass>:<subpass>)로 호출되며, 여기서 <render-pass>는 렌더 패스 번호이고 <subpass>는 서브패스 번호입니다.

프레임 디버거에는 드로우 호출이 포함된 렌더링 패스만 표시됩니다.

프레임 디버거에 대한 자세한 내용은 프레임 디버거를 참조하세요.

 

그래프 렌더링 패스에서 호환성 모드 API 사용

렌더 그래프 시스템 렌더 패스에서 렌더 그래프 AddUnsafePass API를 사용하여 SetRenderTarget과 같은 호환성 모드 API를 사용할 수 있습니다.

AddUnsafePass API를 사용하는 경우 다음 사항이 적용됩니다:

  • RecordRenderGraph 메서드에서는 SetRenderAttachment 메서드를 사용할 수 없습니다. 대신 SetRenderFunc 메서드에서 SetRenderTarget을 사용하세요.
  • URP가 렌더 패스를 최적화할 수 없기 때문에 렌더링 속도가 느려질 수 있습니다.예를 들어 렌더 패스가 활성 색상 버퍼에 기록하는 경우입니다,이후 렌더 패스가 동일한 버퍼에 쓰면 URP는 이를 감지할 수 없습니다.그 결과 URP는 두 렌더 패스를 병합할 수 없게 되고GPU는 버퍼를 불필요하게 메모리 안팎으로 전송합니다.

Unsafe Pass 생성

Unsaft render pass를 만들려면 다음 단계를 따르세요:

1. RecordRenderGraph 메서드에서 AddRasterRenderPass 메서드 대신 AddUnsafePass 메서드를 사용하세요.
예시):

using (var builder = renderGraph.AddUnsafePass<PassData>("My unsafe render pass", out var passData))

2. SetRenderFunc 메서드를 호출할 때는 RasterGraphContext 대신 UnsafeGraphContext 유형을 사용합니다.
예시):

builder.SetRenderFunc(
    (PassData passData, UnsafeGraphContext context) => ExecutePass(passData, context)
);

3. 렌더 패스가 텍스처에 쓰는 경우, 텍스처를 패스 데이터 클래스에 필드로 추가해야 합니다.
예시):

private class PassData
{
    internal TextureHandle textureToWriteTo;
}

4. 렌더 패스가 텍스처에 쓰는 경우 텍스처도 UseTexture 메서드를 사용하여 쓰기 가능으로 설정해야 합니다(

예시):

builder.UseTexture(passData.textureToWriteTo, AccessFlags.Write);

이제 SetRenderFunc 메서드에서 호환성 모드 API를 사용할 수 있습니다.

예제

다음 예제는 호환성 모드 SetRenderTarget API를 사용하여 렌더링 패스 중에 렌더링 대상을 활성 색상 버퍼로 설정한 다음 표면 노멀을 색상으로 사용하여 오브젝트를 그립니다.

using UnityEngine;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class DrawNormalsToActiveColorTexture : ScriptableRendererFeature
{

    DrawNormalsPass unsafePass;

    public override void Create()
    {
        unsafePass = new DrawNormalsPass();
        unsafePass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(unsafePass);
    }

    class DrawNormalsPass : ScriptableRenderPass
    {
        private class PassData
        {
            internal TextureHandle activeColorBuffer;
            internal TextureHandle cameraNormalsTexture;
        }

        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
        {
            using (var builder = renderGraph.AddUnsafePass<PassData>("Draw normals", out var passData))
            {
                // Make sure URP generates the normals texture
                ConfigureInput(ScriptableRenderPassInput.Normal);

                // Get the frame data
                UniversalResourceData resourceData = frameContext.Get<UniversalResourceData>();

                // Add the active color buffer to our pass data, and set it as writeable 
                passData.activeColorBuffer = resourceData.activeColorTexture;
                builder.UseTexture(passData.activeColorBuffer, AccessFlags.Write);                

                // Add the camera normals texture to our pass data 
                passData.cameraNormalsTexture = resourceData.cameraNormalsTexture;
                builder.UseTexture(passData.cameraNormalsTexture);

                builder.AllowPassCulling(false);

                builder.SetRenderFunc((PassData data, UnsafeGraphContext context) => ExecutePass(data, context));
            }
        }

        static void ExecutePass(PassData passData, UnsafeGraphContext context)
        {
            // Create a command buffer for a list of rendering methods
            CommandBuffer unsafeCommandBuffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd);

            // Add a command to set the render target to the active color buffer so URP draws to it
            context.cmd.SetRenderTarget(passData.activeColorBuffer);

            // Add a command to copy the camera normals texture to the render target
            Blitter.BlitTexture(unsafeCommandBuffer, passData.cameraNormalsTexture, new Vector4(1, 1, 0, 0), 0, false);
        }

    }

}

다른 예는 유니버설 렌더 파이프라인(URP) 패키지 샘플에서UnsafePass라는예제를 참조하세요 .

 

URP용 렌더 그래프 뷰어 창 참조

렌더 그래프 뷰어 창에는 유니버설 렌더 파이프라인 (URP)의 현재 에 대한 렌더 그래프가 표시됩니다.

렌더 그래프 뷰어 창에 대한 자세한 내용은 렌더 그래프 분석을 참조하세요.

도구 모음

컨트롤자식 컨트롤설명

Capture 현재 프레임의 렌더링 그래프를 표시합니다.
Render graph 프로젝트에서 표시할 렌더 그래프를 선택합니다.
Camera
렌더링 루프를 표시할 카메라를 선택합니다.
Pass Filter 표시할 렌더 패스를 선택합니다.
  Nothing 렌더링 패스를 표시하지 않습니다.
  Everything 모든 렌더링 패스를 표시합니다.
  Culled 최종 이미지에 영향을 미치지 않으므로 URP가 렌더 그래프에 포함하지 않은 렌더 패스를 표시합니다.
  Raster 렌더그래프 추가 래스터 렌더 패스를 사용하여 생성한 래스터 렌더 패스만 표시합니다.
  Unsafe 호환성 모드 API를 사용하는 렌더 패스만 표시합니다. 렌더 그래프 렌더 패스에서 호환성 모드 API 사용을 참조하십시오.
  Compute 렌더그래프 추가 계산 패스를 사용하여 생성된 계산 렌더 패스만 표시합니다.
Resource Filter 표시할 리소스를 선택합니다.
  Nothing 리소스를 표시하지 않습니다.
  Everything 모든 리소스를 표시합니다.
  Imported 임포트 텍스처를 사용하여 렌더 그래프에 임포트한 리소스만 표시합니다.
  Textures 텍스처만 표시합니다.
  Buffers 버퍼만 표시합니다.
  Acceleration Structures 컴퓨트 렌더 패스에 사용된 가속 구조만 표시합니다.

메인 윈도우

기본 창은 렌더링 그래프에 렌더링 패스를 표시하는 타임라인 그래프입니다. 다음과 같은 내용이 표시됩니다:

  • 왼쪽에는 렌더 패스가 사용하는 리소스 목록이 URP가 생성하는 순서대로 표시됩니다.
  • 상단에는 렌더 패스의 목록이 URP가 실행하는 순서대로 표시됩니다.

그래프에서 렌더 패스와 텍스처가 만나는 지점에 리소스 액세스 블록이 렌더 패스가 리소스를 사용하는 방법을 표시합니다. 액세스 블록은 다음과 같은 아이콘과 색상을 사용합니다:

액세스 차단 아이콘 또는 색상설명

Dotted lines 리소스가 아직 생성되지 않았습니다.
Green 렌더 패스는 리소스에 대한 읽기 전용 액세스 권한이 있습니다. 렌더 패스는 리소스를 읽을 수 있습니다.
Red 렌더 패스는 리소스에 대한 쓰기 전용 액세스 권한을 가집니다. 렌더 패스는 리소스에 쓸 수 있습니다.
Green and red 렌더 패스는 리소스에 대한 읽기-쓰기 액세스 권한이 있습니다. 렌더 패스는 리소스에서 읽거나 쓸 수 있습니다.
Grey 렌더 패스가 리소스에 액세스할 수 없습니다.
Globe icon 렌더 패스는 텍스처를 글로벌 리소스로 설정합니다. 지구본 아이콘의 배경이 회색인 경우 리소스를 TextureHandle 오브젝트로 렌더 그래프로 가져온 것이며, 패스는 SetGlobalTextureAfterPass API를 사용합니다. 렌더 그래프 텍스처 생성렌더 패스 간 텍스처 전송을 참조하세요.
F 렌더 패스는 프레임버퍼 페치로 리소스를 읽을 수 있습니다. 프레임버퍼 가져오기를 사용하여 현재 프레임버퍼 가져오기를 참조하십시오.
Blank 리소스가 메모리에서 할당 해제되었으므로 더 이상 존재하지 않습니다.

액세스 블록을 선택하여 리소스 목록에서 리소스를 표시하고 패스 인스펙터 목록에서 렌더링 패스를 표시합니다.

렌더 패스

콘트롤 설명

Render pass name 렌더 패스의 이름입니다. 이 이름은 추가 래스터 렌더 패스 또는 추가 계산 패스 메서드에서 설정됩니다.
Merge bar URP가 이 패스를 다른 패스와 병합한 경우 렌더 그래프 뷰어에 병합된 패스 아래에 파란색 막대가 표시됩니다.
Resource access overview bar 렌더 패스 이름을 선택하면 리소스 액세스 개요 표시줄에 선택한 패스 및 관련 패스에 대한 정보가 표시됩니다. 자세한 정보를 보려면 개요 블록 위로 커서를 가져가세요. 개요 블록을 선택하여 렌더링 패스에 대한 C# 파일을 엽니다.

개요 블록은 다음 색상을 사용합니다:
- 흰색: 흰색: 선택한 패스입니다.
- 회색: 패스가 선택한 패스와 관련이 없습니다.
- 파란색: 패스가 선택한 패스가 사용하는 리소스에서 읽거나 쓰는 중입니다.
- 파란색으로 깜박입니다: 패스가 선택한 패스가 사용하는 리소스에서 읽거나 쓰고 있으며 현재 패스와 병합할 수 있습니다.

리소스스

속성 설명

Resource type 리소스 유형입니다. 다음 스크린샷을 참조하세요.
Resource name 리소스 이름입니다.
Imported resource 리소스를 가져온 경우 왼쪽을 향한 화살표를 표시합니다. 렌더 그래프 시스템으로 텍스처 임포트를 참조하십시오.

렌더 그래프 뷰어 아이콘

리소스 유형으로 사용되는 아이콘입니다.
A: 텍스처.
B: 가속 구조.
C: 버퍼.

리소스 목록

리소스 목록에서 리소스를 선택하면 해당 리소스에 대한 정보를 펼치거나 접을 수 있습니다.

검색창을 사용하여 이름으로 리소스를 찾을 수도 있습니다.

속성 설명

Resource name The resource name.
Imported resource 리소스를 가져온 경우 왼쪽을 향한 화살표를 표시합니다.
Size 리소스 크기( 픽셀 단위 ).
Format 텍스처 형식입니다. 텍스처 형식에 대한 자세한 내용은 그래픽 형식 을 참조하십시오.
Clear URP가 텍스처를 지우면 True를 표시합니다.
BindMS 텍스처가 멀티샘플링된 텍스처로 바인딩되는지 여부입니다. 멀티샘플링된 텍스처에 대한 자세한 내용은 RenderTextureDescriptor.BindMS 를 참조하십시오.
Samples 멀티샘플 안티앨리어싱(MSAA)이 텍스처를 샘플링하는 횟수입니다. 앤티 앨리어싱을 참조하십시오.
Memoryless 타일 기반 지연 렌더링(TBDR)을 사용하는 모바일 플랫폼에서 리소스가 타일 메모리에 저장된 경우 True를 표시합니다. TBDR에 대한 자세한 내용은 렌더 그래프 시스템 소개 를 참조하십시오.

패스 목록

메인 창에서 렌더 패스를 선택하면 패스 목록에 렌더 패스에 대한 정보가 표시됩니다.

검색 창을 사용하여 이름으로 렌더링 패스를 찾을 수도 있습니다.

속성 설명

Pass name 렌더 패스 이름입니다. URP가 여러 패스를 병합한 경우 이 프로퍼티는 병합된 모든 패스의 이름을 표시합니다.
Native Render Pass Info URP가 여러 렌더 패스를 병합하여 이 렌더 패스에 대한 네이티브 렌더 패스를 생성했는지 여부에 대한 정보를 표시합니다. 네이티브 렌더 패스에 대한 자세한 내용은 렌더 그래프 시스템 소개 를 참조하십시오.
Pass break reasoning URP가 이 렌더 패스를 다음 렌더 패스와 병합할 수 없는 이유를 표시합니다.

렌더 그래프 패스 정보

렌더 그래프 패스 정보 섹션에는 렌더 패스 및 사용하는 각 리소스에 대한 정보가 표시됩니다.

URP가 여러 패스를 이 패스로 병합한 경우 섹션에 병합된 각 패스에 대한 정보가 표시됩니다.

속성 설명

Name 렌더 패스 이름입니다.
Attachment dimensions 렌더 패스가 사용하는 리소스의 크기(픽셀 단위)입니다. 렌더 패스가 리소스를 사용하지 않는 경우 0x0x0을 표시합니다.
Has depth attachment 리소스에 뎁스 텍스처가 있는지 여부입니다.
MSAA samples 멀티샘플 앤티 앨리어싱(MSAA)이 텍스처를 샘플링하는 횟수입니다. 앤티 앨리어싱을 참조하십시오.
Async compute 렌더 패스가 컴퓨팅 셰이더를 사용하여 리소스에 액세스할지 여부입니다.

첨부 파일 로드/저장 작업

첨부 파일 로드/저장 작업 섹션에는 렌더 패스가 사용하는 리소스가 표시됩니다. 렌더 패스가 리소스를 사용하지 않는 경우 이 섹션에는 첨부 파일 없음이 표시됩니다.

속성 설명

Name 리소스 이름입니다.
Load Action 리소스에 대한 로드 액션입니다. 렌더버퍼로드 액션을 참조하십시오.
Store Action 리소스에 대한 저장 액션과 URP가 나중에 다른 렌더 패스나 그래프 외부에서 리소스를 사용하는 방식입니다. 렌더버퍼스토어 액션을 참조하십시오.