Version: Unity 6.0 (6000.0)
언어 : 한국어
URP의 렌더 그래프 시스템에서 텍스처 생성
Add a texture to the frame data in URP

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

렌더 패스 간에 텍스처를 전송할 수 있습니다. 하나의 렌더 패스에서 텍스처를 생성하고 이후의 렌더 패스에서 해당 텍스처를 읽어야 하는 경우가 이에 해당합니다.

렌더 패스 간에 텍스처를 전송하는 방법은 다음과 같습니다.

렌더 패스 외부에도 텍스처를 저장할 수 있습니다(예: 스크립터블 렌더러 기능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);
}

아직 SetRenderFunc를 호출하지 않았다면 빈 렌더 함수 또한 추가해야 합니다. 예시:

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

이제 다음을 수행할 수 있습니다.

  • UseGlobalTexture() 또는 UseAllGlobalTextures() API를 사용하여 다른 렌더 패스에서 텍스처에 액세스합니다.
  • 씬의 모든 머티리얼에 텍스처를 사용합니다.
URP의 렌더 그래프 시스템에서 텍스처 생성
Add a texture to the frame data in URP