MRT: Multiple Render Targets

public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
    TextureHandle[] handles = new TextureHandle[3];
    for (int i = 0; i < 3; i++)
    {
        handles[i] = renderGraph.ImportTexture(m_RTs[i], m_RTInfos[i]);
    }

    using (IRasterRenderGraphBuilder builder = renderGraph.AddRasterRenderPass("MRT Pass", out PassData passData))
    {
        UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();

        passData.colorTextureHandle = resourceData.activeColorTexture;
        passData.texName = m_texName;
        passData.material = m_Material;


        builder.UseTexture(passData.colorTextureHandle);
        for (int i = 0; i < 3; i++)
        {
            builder.SetRenderAttachment(handles[i], i);
        }
        builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => ExecutePass(data, rgContext));
    }
}

static void ExecutePass(PassData data, RasterGraphContext rgContext)
{
    data.material.SetTexture(name: data.texName, value: data.colorTextureHandle);
    rgContext.cmd.DrawProcedural(Matrix4x4.identity, data.material, shaderPass: 0, MeshTopology.Triangles, vertexCount: 3);
}
RTHandle[] m_RTs = new RTHandle[3];
RenderTargetInfo[] m_RTInfos = new RenderTargetInfo[3];

public void Setup(string texName, Material material, RenderTexture[] renderTextures)
{
    m_Material = material;
    m_texName = string.IsNullOrEmpty(texName) ? "_ColorTexture" : texName;

    for (int i = 0; i < 3; i++)
    {
        RenderTexture rednerTexture = renderTextures[i];
        if (m_RTs[i] == null || m_RTs[i].rt != rednerTexture)
        {
            if (m_RTs[i] != null)
            {
                m_RTs[i].Release();
            }

            m_RTs[i] = RTHandles.Alloc(rednerTexture, name: $"ChannelTexture[{i}]");
            m_RTInfos[i] = new RenderTargetInfo
            {
                format = rednerTexture.graphicsFormat,
                height = rednerTexture.height,
                width = rednerTexture.width,
                bindMS = rednerTexture.bindTextureMS,
                volumeDepth = rednerTexture.volumeDepth,
                msaaSamples = 1,
            };
        }
    }
}
Shader "Hidden/MrtColor"
{
    Properties
    {
        _ColorTexture("ColorTexture", 2D) = "white" {}
    }
    SubShader
    {
        Cull Off
        ZWrite Off

        Pass
        {
            HLSLPROGRAM
            #pragma vertex Vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GlobalSamplers.hlsl"

            TEXTURE2D_X(_ColorTexture);

            struct Attributes
            {
                uint vertexID : SV_VertexID;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 texcoord   : TEXCOORD0;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            Varyings Vert(Attributes input)
            {
                Varyings output;

                output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
                output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);

                return output;
            }
    

            // MRT shader
            struct FragmentOutput
            {
                half4 dest0 : SV_Target0;
                half4 dest1 : SV_Target1;
                half4 dest2 : SV_Target2;
            };

            FragmentOutput frag(Varyings input) : SV_Target
            {
                half4 color = SAMPLE_TEXTURE2D_X(_ColorTexture, sampler_LinearRepeat, input.texcoord); 
                FragmentOutput output;
                output.dest0 = half4(color.r, 0.0, 0.0, 1.0);
                output.dest1 = half4(0.0, color.g, 0.0, 1.0);
                output.dest2 = half4(0.0, 0.0, color.b, 1.0);
                return output;
            }
            ENDHLSL
        }
    }
}

Full screen quad vs full screen triangle

  • 사각형의 전체화면 그리기 위해
    • (full screen quad) 삼각형 2개로 사각형을 만드는것이 아닌
    • (full screen triangle) 삼각형을 크게 그려서 삐저나온 부분을 잘라 사각형 그림.

rgContext.cmd.DrawProcedural(Matrix4x4.identity, data.material, shaderPass: 0, MeshTopology.Triangles, vertexCount: 3);