SRP (Scriptable Render Pipeline)

RenderPipelineAsset.asset

  • 유니티에서 그래픽스 파이프 라인을 관리한다. 여러 Renderer를 가질 수 있다.
// 런타임 렌더파이프라인에셋 교체

// Edit> Project Settings> Scriptable Render Pipeline Settings

// 혹은, 이하 스크립트
public RenderPipelineAsset _renderPipelineAsset;

GraphicsSettings.renderPipelineAsset = _renderPipelineAsset;
// 클래스를 만들어서 사용자 렌더파이프라인에셋 만들기
[CreateAssetMenu(menuName = "Rendering/CustomRenderPipelineAsset")]
public class CustomRenderPipelineAsset : RenderPipelineAsset
{
    protected override RenderPipeline CreatePipeline()
    {
        return new CustomRenderPipeline();
    }
}

public class CustomRenderPipeline : RenderPipeline
{
    protected override void Render(ScriptableRenderContext context, Camera[] cameras);
}

RenderGraph

TODO

RenderGraph - cont

  • https://github.com/alexuhui/MySRP/blob/main/Assets/Custom%20RP/ShaderLibrary/Common.hlsl
  • https://catlikecoding.com/unity/custom-srp/2-0-0/
using UnityEngine.Experimental.Rendering.RenderGraphModule;

readonly RenderGraph renderGraph = new("Custom SRP Render Graph");

protected override void Dispose(bool disposing)
{
    …
    renderGraph.Cleanup();
}

var renderGraphParameters = new RenderGraphParameters
{
    commandBuffer = CommandBufferPool.Get(),
    currentFrameIndex = Time.frameCount,
    executionName = "Render Camera",
    scriptableRenderContext = context
};

using (renderGraph.RecordAndExecute(renderGraphParameters))
{

}
CommandBufferPool.Release(renderGraphParameters.commandBuffer);
renderGraph.EndFrame();

Example

RenderPipeline

Pass
{
    Tags
    {
        // LightMode 태그는 라이팅 파이프 라인에서 패스의 역할을 정의.
        "LightMode" = "CustomLightMode"
    }
}

[CreateAssetMenu(menuName = "Rendering/CustomRenderPipelineAsset")]
public class CustomRenderPipelineAsset : RenderPipelineAsset
{
    protected override RenderPipeline CreatePipeline()
    {
        return new CustomRenderPipeline();
    }
}

// ==========================================================================
public class CustomRenderPipeline : RenderPipeline
{
    CustomRenderer _renderer = new CustomRenderer();

    protected override void Render(ScriptableRenderContext context, Camera[] cameras)
    {
        foreach (Camera cam in cameras)
        {
            _renderer.Render(ref context, cam);
        }
    }
}

// ==========================================================================
public class CustomRenderer
{
    readonly static ShaderTagId unlitShaderTagId = new ShaderTagId("CustomLightMode");

    public void Render(ref ScriptableRenderContext context, Camera cam)
    {
        // ...
        context.Submit();                 // 실행
    }
}
context.SetupCameraProperties(camera); // cmd전에 설정해주자(빠른 지우기)
var cmd = new CommandBuffer();
cmd.ClearRenderTarget
context.ExecuteCommandBuffer(cmd); // enqueue cmd
cmd.Release();
context.Submit();                 // 실행
var cmd = new CommandBuffer();
cmd.BeginSample(string sampleName); // profiler begin
cmd.EndSample(string sampleName);   // profiler end
// 컬링
if (!CulllResults.GetCullingParameters(camera, out ScriptableCullingParameters cullingParams))
{
    continue;
}
CullResults cullingResults = context.Cull(ref cullingParams);

SortingSettings sortingSettings = new SortingSettings(cam);
DrawingSettings drawingSettings = new DrawingSettings(unlitShaderTagId, sortingSettings);
FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.opaque);

context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
context.DrawRenderers             // 렌더링
context.DrawSkybox(camera)        // Skybox
// cs
var cmd = new CommandBuffer();
cmd.SetGlobalVector("_LightDir", new Vector4(0, 1, 0, 0));
context.ExecuteCommandBuffer(cmd);
cmd.Release();

// shader
CBUFFER_START(_Light) // CommandBuffer에서 전송됨
float4 _LightDir;
CBUFFER_END
/// Render Texture 사용.

// RenderTarget Id가 필요
int _TmpShaderProperty = Shader.PropertyToID("_TmpShaderProperty");

{
    var cmd = new CommandBuffer();
    // https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.GetTemporaryRT.html
    // GetTemporaryRT(int nameID, int width, int height, int depthBuffer, FilterMode filter, RenderTextureFormat format, RenderTextureReadWrite readWrite, int antiAliasing, bool enableRandomWrite);
    // GetTemporaryRT(int nameID, RenderTextureDescriptor desc, FilterMode filter);
    cmd.GetTemporaryRT(_TmpShaderProperty, )
    cmd.SetRenderTarget(RTID);
    cmd.ClearRenderTarget;
    context.ExecuteCommandBuffer(cmd);
    cmd.Release();
}

{
    var cmd = new CommandBuffer();
    cmd.Blit(RTID, BuiltinRenderTextureType.CameraTarget);
    cmd.ReleaseTemporaryRT(TemporaryRTID);
    context.ExecuteCommandBuffer(cmd);
    cmd.Release();
}

ScriptableRenderPass


...

CullResults cr = CullResults.Cull(ref cullingParams, context);
InitializeRenderingData(settings, ref cameraData, ref cullResults, out var renderingData);
renderer.Setup(context, ref renderingData); // RenderPass 쌓기.
renderer.Execute(context, ref renderingData);
public struct RenderingData
{
    public CullingResults cullResults;
    public CameraData cameraData;
    public LightData lightData;
    public ShadowData shadowData;
    public PostProcessingData postProcessingData;
    public bool supportsDynamicBatching;
    public PerObjectData perObjectData;
    public bool postProcessingEnabled;
}
- ScriptableRenderContext
- ScriptableRenderer (abstract class)
  - public abstract void Setup(ScriptableRenderContext context, ref RenderingData renderingData);

- ScriptableRendererFeature
RenderingData
RenderPassEvent
RenderTargetHandle

Ref