Version: Unity 6.0 (6000.0)
언어 : 한국어
URP에서 렌더 텍스처에 카메라의 출력 렌더링
URP에서의 카메라 렌더링 순서

URP에서 렌더 요청 생성

URP(유니버설 렌더 파이프라인) 렌더링 루프 외부의 렌더 텍스처에 카메라가 렌더링하도록 트리거하려면 C# 스크립트에서 SubmitRenderRequest API를 사용하십시오.

이 예시는 렌더 요청과 콜백을 사용하여 이러한 요청의 진행 상황을 모니터링하는 방법을 보여줍니다. 예시 코드 섹션에서 전체 코드 샘플을 확인할 수 있습니다.

카메라 스택에서 단일 카메라 렌더링

카메라 스택 전체를 고려하지 않으면서 단일 카메라를 렌더링하려면 UniversalRenderPipeline.SingleCameraRequest API를 사용하십시오. 다음 과정을 따르십시오.

  1. 이름이 SingleCameraRenderRequestExample인 C# 스크립트를 생성하고 아래에 제시된 using 문을 추가합니다.

    using System.Collections;
    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class SingleCameraRenderRequestExample : MonoBehaviour
    {
    
    }
    
  2. 렌더링할 카메라와 렌더 텍스처를 저장할 배열을 생성합니다.

    public class SingleCameraRenderRequestExample : MonoBehaviour
    {
        public Camera[] cameras;
        public RenderTexture[] renderTextures;
    }
    
  3. 스크립트 실행을 계속하기 전에 Start 메서드에서 camerasrenderTextures 배열이 유효하며 올바른 데이터를 포함하고 있는지 확인하도록 합니다.

    void Start()
    {
        // Make sure all data is valid before you start the component
        if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
        {
            Debug.LogError("Invalid setup");
            return;
        }
    }
    
  4. SingleCameraRenderRequest 클래스 내에서 이름이 SendSingleRenderRequests이고 반환 유형이 void인 메서드를 만듭니다.

  5. SendSingleRenderRequests 메서드에서 아래와 같이 cameras 배열을 반복하는 for 루프를 추가합니다.

    void SendSingleRenderRequests()
    {
        for (int i = 0; i < cameras.Length; i++)
        {
    
        }
    }
    
  6. for 루프 내에서 이름이 request인 변수에 UniversalRenderPipeline.SingleCameraRequest 유형의 렌더링 요청을 생성합니다. 그런 다음 활성 렌더 파이프라인이 RenderPipeline.SupportsRenderRequest를 사용하여 이 렌더 요청 유형을 지원하는지 확인합니다.

  7. 활성 렌더 파이프라인이 이 렌더 요청을 지원하는 경우, 카메라 출력의 대상을 renderTextures 배열의 일치하는 렌더 텍스처로 설정합니다. 이후 RenderPipeline.SubmitRenderRequest로 렌더 요청을 제출합니다.

    void SendSingleRenderRequests()
    {
        for (int i = 0; i < cameras.Length; i++)
        {
            UniversalRenderPipeline.SingleCameraRequest request =
                new UniversalRenderPipeline.SingleCameraRequest();
    
            // Check if the active render pipeline supports the render request
            if (RenderPipeline.SupportsRenderRequest(cameras[i], request))
            {
                // Set the destination of the camera output to the matching RenderTexture
                request.destination = renderTextures[i];
                    
                // Render the camera output to the RenderTexture synchronously
                // When this is complete, the RenderTexture in renderTextures[i] contains the scene rendered from the point
                // of view of the Camera in cameras[i]
                RenderPipeline.SubmitRenderRequest(cameras[i], request);
            }
        }
    }
    
  8. SendSingleRenderRequest 메서드 위에 이름이 RenderSingleRequestNextFrameIEnumerator 인터페이스를 만듭니다.

  9. RenderSingleRequestNextFrame 안에서 메인 카메라가 렌더링을 완료할 때까지 기다린 다음 SendSingleRenderRequest를 호출합니다. 프레임이 끝날 때까지 기다린 후 StartCoroutine으로 코루틴에서 RenderSingleRequestNextFrame을 재시작합니다.

    IEnumerator RenderSingleRequestNextFrame()
    {
        // Wait for the main camera to finish rendering
        yield return new WaitForEndOfFrame();
    
        // Enqueue one render request for each camera
        SendSingleRenderRequests();
    
        // Wait for the end of the frame
        yield return new WaitForEndOfFrame();
    
        // Restart the coroutine
        StartCoroutine(RenderSingleRequestNextFrame());
    }
    
  10. Start 메서드에서 StartCoroutine으로 코루틴에서 RenderSingleRequestNextFrame을 호출합니다.

    void Start()
    {
        // Make sure all data is valid before you start the component
        if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
        {
            Debug.LogError("Invalid setup");
            return;
        }
    
        // Start the asynchronous coroutine
        StartCoroutine(RenderSingleRequestNextFrame());
    }
    
  11. 에디터에서 빈 게임 오브젝트를 씬에 생성하고 SingleCameraRenderRequestExample.cs컴포넌트로서 추가합니다.

  12. 인스펙터 창에서 렌더링할 카메라를 cameras 목록에 추가하고 렌더링할 렌더 텍스처를 renderTextures 목록에 추가합니다.

참고: cameras 목록의 카메라 개수와 renderTextures 목록의 렌더 텍스처 개수는 동일해야 합니다.

플레이 모드를 시작하면 추가한 카메라들이 추가한 렌더 텍스처들에 렌더링됩니다.

카메라가 렌더링을 완료하는 시점 확인

카메라가 렌더링을 완료하는 시점을 확인하려면 RenderPipelineManager API의 콜백을 사용하십시오.

다음 예시는 RenderPipelineManager.endContextRendering 콜백을 사용합니다.

  1. SingleCameraRenderRequestExample.cs 파일 맨 위에 using System.Collections.Generic을 추가합니다.

  2. Start 메서드 끝에 endContextRendering 콜백을 구독합니다.

    void Start()
    {
        // Make sure all data is valid before you start the component
        if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
        {
            Debug.LogError("Invalid setup");
            return;
        }
    
        // Start the asynchronous coroutine
        StartCoroutine(RenderSingleRequestNextFrame());
            
        // Call a method called OnEndContextRendering when a camera finishes rendering
        RenderPipelineManager.endContextRendering += OnEndContextRendering;
    }
    
  3. 이름이 OnEndContextRendering인 메서드를 생성합니다. Unity는 endContextRendering 콜백이 트리거될 때 이 메서드를 실행합니다.

    void OnEndContextRendering(ScriptableRenderContext context, List<Camera> cameras)
    {
        // Create a log to show cameras have finished rendering
        Debug.Log("All cameras have finished rendering.");
    }
    
  4. endContextRendering 콜백에서 OnEndContextRendering 메서드를 구독 취소하려면 OnDestroy 메서드를 SingleCameraRenderRequestExample 클래스에 추가합니다.

    void OnDestroy()
    {
        // End the subscription to the callback
        RenderPipelineManager.endContextRendering -= OnEndContextRendering;
    }
    

이제 이 스크립트는 이전과 같이 작동하되, 렌더링이 완료된 카메라에 대한 메시지를 콘솔 창에 기록합니다.

예제 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class SingleCameraRenderRequest : MonoBehaviour
{
    public Camera[] cameras;
    public RenderTexture[] renderTextures;

    void Start()
    {
        // Make sure all data is valid before you start the component
        if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
        {
            Debug.LogError("Invalid setup");
            return;
        }

        // Start the asynchronous coroutine
        StartCoroutine(RenderSingleRequestNextFrame());
        
        // Call a method called OnEndContextRendering when a camera finishes rendering
        RenderPipelineManager.endContextRendering += OnEndContextRendering;
    }

    void OnEndContextRendering(ScriptableRenderContext context, List<Camera> cameras)
    {
        // Create a log to show cameras have finished rendering
        Debug.Log("All cameras have finished rendering.");
    }

    void OnDestroy()
    {
        // End the subscription to the callback
        RenderPipelineManager.endContextRendering -= OnEndContextRendering;
    }

    IEnumerator RenderSingleRequestNextFrame()
    {
        // Wait for the main camera to finish rendering
        yield return new WaitForEndOfFrame();

        // Enqueue one render request for each camera
        SendSingleRenderRequests();

        // Wait for the end of the frame
        yield return new WaitForEndOfFrame();

        // Restart the coroutine
        StartCoroutine(RenderSingleRequestNextFrame());
    }

    void SendSingleRenderRequests()
    {
        for (int i = 0; i < cameras.Length; i++)
        {
            UniversalRenderPipeline.SingleCameraRequest request =
                new UniversalRenderPipeline.SingleCameraRequest();

            // Check if the active render pipeline supports the render request
            if (RenderPipeline.SupportsRenderRequest(cameras[i], request))
            {
                // Set the destination of the camera output to the matching RenderTexture
                request.destination = renderTextures[i];
                
                // Render the camera output to the RenderTexture synchronously
                RenderPipeline.SubmitRenderRequest(cameras[i], request);

                // At this point, the RenderTexture in renderTextures[i] contains the scene rendered from the point
                // of view of the Camera in cameras[i]
            }
        }
    }
}
URP에서 렌더 텍스처에 카메라의 출력 렌더링
URP에서의 카메라 렌더링 순서