Unity 6.3
0 онлайн 102 гостей 3 в системе
Вход
Конвейеры отображения Шаг 104 из 129

Использование интерфейса CommandBuffer в графе рендеринга

Вы можете использовать график рендеринга AddUnsafePass API для использования CommandBuffer API интерфейса, такие как SetRenderTarget в графе рендеринга система рендеринга проходит.

AddUnsafePass API дает доступ к UnsafeCommandBuffer, который дает доступ к большему количеству функций CommandBuffer, чем RasterCommandBuffer API.

Примечание: Как AddUnsafePass, так и RasterCommandBuffer ограничивают доступ к некоторым функциям commandBuffer, чтобы RenderGraph мог лучше оптимизировать кадр. Самая важная функция UnsafeCommandbuffer предоставляет вам доступ к SetRenderTarget.

Если вы используете AddUnsafePass API, применяется следующее:

  • Вы не можете использовать метод SetRenderAttachment в методе RecordRenderGraph. Вместо этого используйте SetRenderTarget в методе SetRenderFunc.
  • Отображение может быть медленнее, потому что система графического отображения не может оптимизировать проход отображения. Например, если ваш проход отображения записывает в активный цветовой буфер, система графического отображения не может определить, записывает ли более поздний проход отображения в тот же буфер. В результате система графического отображения не может объединить два прохода отображения, и GPU ненужным образом передаёт буфер в память и из нее.

Создание небезопасного прохода отображения

Чтобы создать небезопасный проход отображения, выполните следующие действия.

  1. В методе RecordRenderGraph используйте метод AddUnsafePass вместо метода AddRasterRenderPass.

    Например:

    using (var builder = renderGraph.AddUnsafePass<PassData>("My unsafe render pass", out var passData))
    
  2. При вызове метода SetRenderFunc используйте тип UnsafeGraphContext вместо типа RasterGraphContext.

    Например:

    builder.SetRenderFunc(
        static (PassData passData, UnsafeGraphContext context) => ExecutePass(passData, context)
    );
    
  3. Если ваш проход рендеринга пишет в текстуру, добавьте её как поле в класс данных прохода.

    Например:

    class PassData
    {
        public TextureHandle textureToWriteTo;
    }
    
  4. Если ваш проход рендеринга записывает текстуру, установите текстуру как записываемую с помощью метода UseTexture.

    Например:

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

Теперь в своём методе можно использовать API интерфейса CommandBuffer SetRenderFunc метод.

Пример

В следующем примере используется интерфейс CommandBuffer 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
    {
        class PassData
        {
            public TextureHandle activeColorBuffer;
            public 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);

                // Make sure the render graph system keeps the render pass, even if it's not used in the final frame.
                // Don't use this in production code, because it prevents the render graph system from removing the render pass if it's not needed.
                builder.AllowPassCulling(false);

                builder.SetRenderFunc(static (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);
        }

    }

}

Другие примеры см. в примере, названном UnsafePass в примерах пакета Universal Render Pipeline (URP).