рдПрдХрддрд╛ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рд░реЗрдВрдбрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рдкреНрд░рднрд╛рд╡ рдмрдирд╛рдирд╛

рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рд░реЗрдВрдбрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ, рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд░реЗрдВрдбрд░рд░ рдлрд╝реАрдЪрд░ рдмрдирд╛рдХрд░, рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд░реЗрдВрдбрд░рд┐рдВрдЧ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдирдП рдкрд╛рд╕ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдЖрдк рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рднрд╛рд╡ рдкреИрджрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдЖрд▓реЗрдЦ рдореЗрдВ, ScriptableRendererFeature рдФрд░ ScriptableRenderPass рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд░реВрдкрд░реЗрдЦрд╛ рдкреНрд░рднрд╛рд╡ рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдХреБрдЫ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред

рд░реВрдкрд░реЗрдЦрд╛ рдкреНрд░рднрд╛рд╡


рдкрд░рд┐рдЪрдп рдпрд╛ рдХреБрдЫ рд╢рдмреНрдж рд░реЗрдВрдбрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ


рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд░реЗрдВрдбрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдЖрдкрдХреЛ C # рдореЗрдВ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рдХреЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдФрд░ рд╡рд╕реНрддреБрдУрдВ, рд░реЛрд╢рдиреА, рдЫрд╛рдпрд╛, рдФрд░ рдЕрдиреНрдп рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреНрд░рдо рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рд░реЗрдВрдбрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдПрдХ рддреИрдпрд╛рд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯреЗрдб рд░реЗрдВрдбрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╣реИ рдЬреЛ рдпреВрдирд┐рдЯреА рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдХреА рдЧрдИ рд╣реИ рдФрд░ рдкреБрд░рд╛рдиреЗ рдмрд┐рд▓реНрдЯ-рдЗрди рдЖрд░рдкреА рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдЖрд░рдкреА рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдФрд░ рдЕрдкрдиреЗ рдЦреБрдж рдХреЗ рдбреНрд░рд╛рдЗрдВрдЧ рдкрд╛рд╕ (ScriptableRendererFeature рдФрд░ ScriptableRenderPeature) рдмрдирд╛рдХрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╡рд░реНрддрдорд╛рди рд▓реЗрдЦ рд╣реЛрдЧрд╛ред рдпрд╣ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ рдЬреЛ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдЖрд░рдкреА рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдФрд░, рд╢рд╛рдпрдж, рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдЖрд░рдкреА рдореЗрдВ рдореМрдЬреВрджрд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯреЗрдмрд▓рд░реЗрдВрдбрд░рдкрд╛рд╕ рдХреЗ рдХрд╛рдо рдХреЛ рдмреЗрд╣рддрд░ рдврдВрдЧ рд╕реЗ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред

рдпрд╣ рд▓реЗрдЦ рдпреВрдирд┐рдЯреА 2019.3 рдФрд░ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдЖрд░рдкреА 7.1.8 рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ред

рдХрд╛рд░реНрдп рдпреЛрдЬрдирд╛


рд╣рдо рд╕рдордЭреЗрдВрдЧреЗ рдХрд┐ ScriptableRendererFeature рдФрд░ ScriptableRenderPass рдХреИрд╕реЗ рдУрдкреЗрдХ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕реНрдЯреНрд░реЛрдХ рдкреНрд░рднрд╛рд╡ рдмрдирд╛рдиреЗ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ ScriptableRendererFeature рдмрдирд╛рдПрдБ рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рддрд╛ рд╣реИ:

  • рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЦреАрдВрдЪрдирд╛
  • рдзреБрдВрдзрд▓рд╛ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдзреБрдВрдзрд▓рд╛ рдХрд░рдирд╛
  • рдкрд┐рдЫрд▓реЗ рдкрд╛рд╕реЛрдВ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдЫрд╡рд┐рдпреЛрдВ рд╕реЗ рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЖрдХреГрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛

рд╕реНрд░реЛрдд рдлреНрд░реЗрдо -

рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдХреНрд░рдо рдЬреЛ рд╣рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:


рдХрд╛рдо рдХреЗ рджреМрд░рд╛рди, рд╣рдо рдПрдХ рд╢реЗрдбрд░ рдмрдирд╛рдПрдВрдЧреЗ, рдЬрд┐рд╕рдХреЗ рд╡реИрд╢реНрд╡рд┐рдХ рдЧреБрдгреЛрдВ рдореЗрдВ рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рдкрд╛рд╕ рдХреЗ рдкрд░рд┐рдгрд╛рдо рд╕рд╣реЗрдЬреЗ рдЬрд╛рдПрдВрдЧреЗред рдЕрдВрддрд┐рдо рдкрд╛рд╕ рд╕реНрдХреНрд░реАрди рдкрд░ рд╕реНрд╡рдпрдВ shader рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдЧрд╛ред

рд╡реИрд╢реНрд╡рд┐рдХ рдЧреБрдг
, , Properties. тАФ .

тАФ . .

рд░реВрдкрд░реЗрдЦрд╛ рдмрдирд╛рдПрдБ


ScriptableRendererFeature рдХрд╛ рдЙрдкрдпреЛрдЧ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ RP рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо рд░реЗрдВрдбрд░рд┐рдВрдЧ рдорд╛рд░реНрдЧ (ScriptableRenderPass) рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред OutlineFeature рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдБ рдЬреЛ ScriptableRenderFeature рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА рд╣реЛ рдФрд░ рдЙрд╕рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реЛред

using UnityEngine;
using UnityEngine.Rendering.Universal;

public class OutlineFeature : ScriptableRendererFeature
{
    public override void Create()
    { }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    { }
}

рдкрд╛рд╕ рдмрдирд╛рдиреЗ рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдПрдБ () рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ AddRenderPasses () рдирд┐рд░реНрдорд┐рдд рдЗрдВрдЬреЗрдХреНрд╢рди рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрддрд╛рд░ рдореЗрдВ рдЧреБрдЬрд░рддреА рд╣реИред

рддрд░реНрдХ AddRenderPasses ()
ScriptableRenderer тАФ Universal RP. Universal RP Forward Rendering.

RenderingData тАФ , , .

рдЕрдм рдЪрд▓реЛ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдкрд╛рд╕ рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╡рд░реНрддрдорд╛рди рдХрдХреНрд╖рд╛ рдореЗрдВ рд▓реМрдЯ рдЖрдПрдВрдЧреЗред

рд░реЗрдВрдбрд░ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдкрд╛рд╕ рд╣реЛрддреЗ рд╣реИрдВ


рдЗрд╕ рдорд╛рд░реНрдЧ рдХрд╛ рдХрд╛рд░реНрдп рдЫрд╛рдпрд╛ рдХреА рд╡реИрд╢реНрд╡рд┐рдХ рдмрдирд╛рд╡рдЯ рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рд╕рд╛рдордЧреНрд░реА рдХреЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкрд░рдд рд╕реЗ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рд╣реИред рдпрд╣ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ рдЖрд░рдкреА рдореЗрдВ рдЙрдкрд▓рдмреНрдз RenderObjectsPass рдорд╛рд░реНрдЧ рдХрд╛ рд╕рд░рд▓реАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рд╣реЛрдЧрд╛, рд▓рдХреНрд╖реНрдп (RenderTarget) рдореЗрдВ рдПрдХрдорд╛рддреНрд░ рдЕрдВрддрд░ рдХреЗ рд╕рд╛рде рдЬрд╣рд╛рдВ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдПрдХ рд╡рд░реНрдЧ рдмрдирд╛рдПрдБ MyRenderObjectsPass ScriptableRenderPass рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ред рд╣рдо Execute () рдкрджреНрдзрддрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдорд╛рд░реНрдЧ рдХреЗ рд╕рднреА рддрд░реНрдХ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ, рд╕рд╛рде рд╣реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ () рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВрдЧреЗред

using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class MyRenderObjectsPass : ScriptableRenderPass
{
    {
        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        { }
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        { }
    }
}

рдЕрд╕реНрдерд╛рдпреА рдкрд╛рда рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдФрд░ рдмрдирд╛рдиреЗ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ () рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рд▓рдХреНрд╖реНрдп рд╡рд░реНрддрдорд╛рди рдХреИрдорд░реЗ рдХрд╛ рд▓рдХреНрд╖реНрдп рд╣реИ, рдФрд░ рдкрд╛рд╕ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдлрд┐рд░ рд╕реЗ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдмреЗрд╕ рд▓реЙрдЬрд┐рдХ рдЪрд▓рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

рд▓рдХреНрд╖реНрдп рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХрд╛ рдкреНрд░рддрд┐рдкрд╛рджрди


рдПрдХ рдирдП рдкреНрд░рддрд┐рдкрд╛рджрди рд▓рдХреНрд╖реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ RenderTargetHandle рдШреЛрд╖рд┐рдд рдХрд░реЗрдВред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдПрдХ рдЕрд╕реНрдерд╛рдпреА рдмрдирд╛рд╡рдЯ рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕реЗ рд▓рдХреНрд╖реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВред RenderTargetHandle рдореЗрдВ рдкреНрд░рдпреБрдХреНрдд рдЕрд╕реНрдерд╛рдпреА RenderTexture рдХреЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рд╣реИрдВред рдпрд╣ рдЖрдкрдХреЛ рдПрдХ RenderTargetIdentifier рднреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рд░реЗрдВрдбрд░рд┐рдВрдЧ рд▓рдХреНрд╖реНрдп рдХреЛ рдкрд╣рдЪрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ RenderTexture, Texture рдСрдмреНрдЬреЗрдХреНрдЯ, рдЕрд╕реНрдерд╛рдпреА RenderTexture рдпрд╛ рдмрд┐рд▓реНрдЯ-рдЗрди (рдХреИрдорд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдПрдХ рдлреНрд░реЗрдо рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ)ред

рдПрдХ RenderTargetHandle рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ OutlineFeature рдореЗрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдмрдирд╛рдП рдЬрд╛рдиреЗ рдкрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореЗрдВ рднреЗрдЬ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

private RenderTargetHandle _destination;

public MyRenderObjectsPass(RenderTargetHandle destination)
{
    _destination = destination;
}

public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{  
    cmd.GetTemporaryRT(_destination.id, cameraTextureDescriptor);
}

GetTemporaryRT () рд╡рд┐рдзрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрд╕реНрдерд╛рдпреА RenderTexture рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╛рдо (рд╕реБрд╡рд┐рдзрд╛ рдореЗрдВ рдирд╛рдо рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛) рдХреЗ рд╕рд╛рде рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ shader рдЧреБрдг рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред

RenderTexture рдирд┐рдХрд╛рд▓реЗрдВ
ReleaseTemporaryRT() RenderTexture. Execute() FrameCleanup.
, RenderTexture, , .

рдПрдХ рдЕрд╕реНрдерд╛рдпреА рд░реЗрдВрдбрд░рдЯреЗрдХреНрд╕реНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рд╡рд░реНрддрдорд╛рди рдХреИрдорд░реЗ рдХреЗ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдХреИрдорд░реЗ рдХреЗ рд▓рдХреНрд╖реНрдп рдХреЗ рдЖрдХрд╛рд░, рдкреНрд░рд╛рд░реВрдк рдФрд░ рдЕрдиреНрдп рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрддреА рд╣реИред

public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{        
    cmd.GetTemporaryRT(_destination.id, cameraTextureDescriptor);
    ConfigureTarget(_destination.Identifier());
    ConfigureClear(ClearFlag.All, Color.clear);
}

рд▓рдХреНрд╖реНрдп рдФрд░ рдЗрд╕рдХреА рд╕рдлрд╛рдИ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдХреЗрд╡рд▓ рдХреЙрдиреНрдлрд┐рдЧрд░рдЯреИрдЧ () рдФрд░ рдХреНрд▓рд┐рдпрд░рдЯрд╛рд░реНрдЧ () рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ () рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛


рд╣рдо рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╣рдореЗрдВ рдореБрдЦреНрдп рд╡рд┐рд╖рдп рд╕реЗ рдмрд╣реБрдд рджреВрд░ рдФрд░ рджреВрд░ рд▓реЗ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЗ рд▓рд┐рдП, рд╣рдо ScriptableRenderContext.DrawRenderers () рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдХреЗрд╡рд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкрд░рддреЛрдВ рд╕реЗ рдХреЗрд╡рд▓ рдЕрдкрд╛рд░рджрд░реНрд╢реА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЗ рд▓рд┐рдП рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдмрдирд╛рдПрдВред рд▓реЗрдпрд░ рдорд╛рд╕реНрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

...
private List<ShaderTagId> _shaderTagIdList = new List<ShaderTagId>() { new ShaderTagId("UniversalForward") };
private FilteringSettings _filteringSettings;
private RenderStateBlock _renderStateBlock;
...
public MyRenderObjectsPass(RenderTargetHandle destination, int layerMask)
{
    _destination = destination;

    _filteringSettings = new FilteringSettings(RenderQueueRange.opaque, layerMask);
    _renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
}

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
    SortingCriteria sortingCriteria = renderingData.cameraData.defaultOpaqueSortFlags;
    DrawingSettings drawingSettings = CreateDrawingSettings(_shaderTagIdList, ref renderingData, sortingCriteria);

    context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref _filteringSettings, ref _renderStateBlock);
}

рдмрд╣реБрдд рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
CullingResults тАФ ( RenderingData)
FilteringSettings тАФ .
DrawingSettings тАФ .
RenderStateBlock тАФ , (, ..)

UniversalRP рдореЗрдВ рддреИрдпрд╛рд░ RenderObjectsPass рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
, . . RenderObjectsPass, Universal RP, . RenderFeature - :)

рд╕рд╛рдордЧреНрд░реА рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди


рд╣рдо рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рд╡рд╕реНрддреБрдУрдВ рдХреА рдЖрдХреГрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

private Material _overrideMaterial;

public MyRenderObjectsPass(RenderTargetHandle destination, int layerMask,, Material overrideMaterial)
{
...
    _overrideMaterial = overrideMaterial;
...
}

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
...
    DrawingSettings drawingSettings = CreateDrawingSettings(_shaderTagIdList, ref renderingData, sortingCriteria);
    drawingSettings.overrideMaterial = _overrideMaterial;
...
}

рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЫрд╛рдпрд╛рджрд╛рд░


ShaderGraph рдореЗрдВ рдПрдХ рд╕рд╛рдордЧреНрд░реА shader рдмрдирд╛рдПрдБ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд░реНрддрдорд╛рди рдкрд╛рд╕ рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЦреАрдВрдЪрддреЗ рд╕рдордп рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


OutlineFeature рдореЗрдВ рдПрдХ рдорд╛рд░реНрдЧ рдЬреЛрдбрд╝реЗрдВ


рд╡рд╛рдкрд╕ OutlieFeature рдкрд░ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдорд╛рд░реЗ рдкреИрд╕реЗрдЬ рдХреА рд╕реЗрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВред

public class OutlineFeature : ScriptableRendererFeature
{
    [Serializable]
    public class RenderSettings
    {
        public Material OverrideMaterial = null;
        public LayerMask LayerMask = 0;
    }
    ...
}

MyRenderPass рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рдлрд╝реАрд▓реНрдб рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ рдФрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╕реНрддреБрдд рд▓рдХреНрд╖реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд╡реИрд╢реНрд╡рд┐рдХ рдмрдирд╛рд╡рдЯ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдирд╛рдоред

[SerializeField] private string _renderTextureName;
[SerializeField] private RenderSettings _renderSettings;

рдмрдирд╛рд╡рдЯ рдХреА рд╕рдВрдкрддреНрддрд┐ рдФрд░ MyRenderPass рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдПрдВред

private RenderTargetHandle _renderTexture;
private MyRenderObjectsPass _renderPass;

public override void Create()
{
    _renderTexture.Init(_renderTextureName);

    _renderPass = new MyRenderObjectsPass(_renderTexture, _renderSettings.LayerMask, _renderSettings.OverrideMaterial);
}

AddRendererPass рдкрджреНрдзрддрд┐ рдореЗрдВ, рд╣рдо рдЕрдкрдирд╛ рдкрд╛рд╕ рдирд┐рд╖реНрдкрд╛рджрди рдХрддрд╛рд░ рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
    renderer.EnqueuePass(_renderPass);
}

рдЖрдЧреЗ рджреЗрдЦ рд░рд╣рд╛
. , .

рд╕реНрд░реЛрдд рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдкрд╛рд╕ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:


рдбрд┐рдмрдЧрд┐рдВрдЧ
Frame Debug (Windows-Analysis-FrameDebugger).

рдзреБрдВрдзрд▓рд╛ рдкрд╛рд╕


рдЗрд╕ рдорд╛рд░реНрдЧ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдкрд┐рдЫрд▓реЗ рдЪрд░рдг рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдЫрд╡рд┐ рдХреЛ рдзреБрдВрдзрд▓рд╛ рдХрд░рдирд╛ рдФрд░ рдЗрд╕реЗ рд╡реИрд╢реНрд╡рд┐рдХ shader рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рд╕реЗрдЯ рдХрд░рдирд╛ рд╣реИред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдореВрд▓ рдмрдирд╛рд╡рдЯ рдХреЛ рдПрдХ рдЕрд╕реНрдерд╛рдпреА рдПрдХ рдкрд░ рдХрдИ рдмрд╛рд░ рдХреЙрдкреА рдХрд░реЗрдВрдЧреЗ, рдЗрд╕ рдкрд░ рдмреНрд▓рд░ рд╢реЗрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореВрд▓ рдЫрд╡рд┐ рдХреЛ рдЖрдХрд╛рд░ рдореЗрдВ рдХрдо рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдХрдо рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдПрдБ), рдЬреЛ рдЧрдгрдирд╛рдУрдВ рдХреЛ рдЧрддрд┐ рджреЗрдЧрд╛ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреА рдЧреБрдгрд╡рддреНрддрд╛ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

рдЪрд▓рд┐рдП ScriptableRenderPass рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА BlurPass рдХреНрд▓рд╛рд╕ рдмрдирд╛рддреЗ рд╣реИрдВред

using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class BlurPass : ScriptableRenderPass
{
    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    { }
}

рдЪрд▓реЛ рд╕реНрд░реЛрдд, рд▓рдХреНрд╖реНрдп рдФрд░ рдЕрд╕реНрдерд╛рдпреА рдмрдирд╛рд╡рдЯ (рдФрд░ рдЙрдирдХреА рдЖрдИрдбреА) рдХреЗ рд▓рд┐рдП рдЪрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

private int _tmpBlurRTId1 = Shader.PropertyToID("_TempBlurTexture1");
private int _tmpBlurRTId2 = Shader.PropertyToID("_TempBlurTexture2");

private RenderTargetIdentifier _tmpBlurRT1;
private RenderTargetIdentifier _tmpBlurRT2;

private RenderTargetIdentifier _source;
private RenderTargetHandle _destination;

RenderTexture рдХреА рд╕рднреА ID Shader.PropertyID () рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЗрдЯ рдХреА рдЧрдИ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХрд╣реАрдВ рди рдХрд╣реАрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ shader рдЧреБрдг рдореМрдЬреВрдж рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред

рд╢реЗрд╖ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝реЗрдВ, рдЬрд┐рд╕реЗ рд╣рдо рддреБрд░рдВрдд рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдореЗрдВ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

private int _passesCount;
private int _downSample;
private Material _blurMaterial;

public BlurPass(Material blurMaterial, int downSample, int passesCount)
{
    _blurMaterial = blurMaterial;
    _downSample = downSample;
    _passesCount = passesCount;
}

_blurMaterial - рдПрдХ рдзрдмреНрдмрд╛ рдХреЗ рд╕рд╛рде рд╕рд╛рдордЧреНрд░реАред
_downSample - рдмрдирд╛рд╡рдЯ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреБрдгрд╛рдВрдХ
_passesCount - рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмреНрд▓рд░ рдкрд╛рд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ред

рдЕрд╕реНрдерд╛рдпреА рдмрдирд╛рд╡рдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде рдПрдХ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдмрдирд╛рдПрдВ - рдЖрдХрд╛рд░, рдкреНрд░рд╛рд░реВрдк рдФрд░ рдЕрдзрд┐рдХред рдКрдВрдЪрд╛рдИ рдФрд░ рдЖрдХрд╛рд░ рдХреИрдорд░рд╛ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдмрдврд╝рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
    var width = Mathf.Max(1, cameraTextureDescriptor.width >> _downSample);
    var height = Mathf.Max(1, cameraTextureDescriptor.height >> _downSample);
    var blurTextureDesc = new RenderTextureDescriptor(width, height, RenderTextureFormat.ARGB32, 0, 0);
рд╣рдо рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдФрд░ рдЕрд╕реНрдерд╛рдпреА рд░реЗрдВрдбрд░рдЯреЗрдХреНрд╕реНрдЯ рд╕реНрд╡рдпрдВ рднреА рдмрдирд╛рдПрдВрдЧреЗред
    _tmpBlurRT1 = new RenderTargetIdentifier(_tmpBlurRTId1);
    _tmpBlurRT2 = new RenderTargetIdentifier(_tmpBlurRTId2);

    cmd.GetTemporaryRT(_tmpBlurRTId1, blurTextureDesc, FilterMode.Bilinear);
    cmd.GetTemporaryRT(_tmpBlurRTId2, blurTextureDesc, FilterMode.Bilinear);

рд╣рдо рд░реЗрдВрдбрд░рд┐рдВрдЧ рд▓рдХреНрд╖реНрдп рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрджрд▓рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдФрд░ рдЕрд╕реНрдерд╛рдпреА рдмрдирд╛рд╡рдЯ рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕реЗ рд▓рдХреНрд╖реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред

    cmd.GetTemporaryRT(_destination.id, blurTextureDesc, FilterMode.Bilinear);
    ConfigureTarget(_destination.Identifier());
}

рдХрд▓рдВрдХ


рдХреБрдЫ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╡рд┐рд╢реЗрд╖ ScriptableRenderContext рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдЗрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдФрд░ рдХрдорд╛рдВрдб рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдЕрдиреНрдп рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХрдорд╛рдВрдбрдмрдлрд╝рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЬрд┐рд╕реЗ рдкреВрд▓ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЖрджреЗрд╢реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╕рдВрджрд░реНрдн рдореЗрдВ рднреЗрдЬрдиреЗ рдХреЗ рдмрд╛рдж, рдмрдлрд░ рдХреЛ рд╡рд╛рдкрд╕ рдкреВрд▓ рдореЗрдВ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
    var cmd = CommandBufferPool.Get("BlurPass");
    ...
    context.ExecuteCommandBuffer(cmd);
    CommandBufferPool.Release(cmd);
}

Execute () рд╡рд┐рдзрд┐ рдХрд╛ рдЕрдВрддрд┐рдо рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реЛрдЧрд╛ред

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
    var cmd = CommandBufferPool.Get("BlurPass");

    if (_passesCount > 0)
    {
        cmd.Blit(_source, _tmpBlurRT1, _blurMaterial, 0);
        for (int i = 0; i < _passesCount - 1; i++)
        {
            cmd.Blit(_tmpBlurRT1, _tmpBlurRT2, _blurMaterial, 0);
            var t = _tmpBlurRT1;
            _tmpBlurRT1 = _tmpBlurRT2;
            _tmpBlurRT2 = t;
        }
        cmd.Blit(_tmpBlurRT1, _destination.Identifier());
    }
    else
        cmd.Blit(_source, _destination.Identifier());
    context.ExecuteCommandBuffer(cmd);
    CommandBufferPool.Release(cmd);
}

Blit
Blit() .

рд╢реЗрдбрд░


рдзреБрдВрдзрд▓рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╢реЗрдбрд░ рдмрдирд╛рдПрдВ рдЬреЛ рдкрд┐рдХреНрд╕реЗрд▓ рдХреЗ рд░рдВрдЧ рдХреА рдЧрдгрдирд╛ рдЙрд╕рдХреЗ рдирд┐рдХрдЯрддрдо рдкрдбрд╝реЛрд╕рд┐рдпреЛрдВ (рдкрд╛рдВрдЪ рдкрд┐рдХреНрд╕реЗрд▓ рдХрд╛ рдФрд╕рдд рд░рдВрдЧ рдореВрд▓реНрдп) рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдЧрд╛ред

рдмреНрд▓рд░ рд╢реЗрдбрд░
Shader "Custom/Blur"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}

SubShader
{
HLSLINCLUDE

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

struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};

struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};

TEXTURE2D_X(_MainTex);
SAMPLER(sampler_MainTex);
float4 _MainTex_TexelSize;

Varyings Vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = input.uv;
return output;
}

half4 Frag(Varyings input) : SV_Target
{
float2 offset = _MainTex_TexelSize.xy;
float2 uv = UnityStereoTransformScreenSpaceTex(input.uv);

half4 color = SAMPLE_TEXTURE2D_X(_MainTex, sampler_MainTex, input.uv);
color += SAMPLE_TEXTURE2D_X(_MainTex, sampler_MainTex, input.uv + float2(-1, 1) * offset);
color += SAMPLE_TEXTURE2D_X(_MainTex, sampler_MainTex, input.uv + float2( 1, 1) * offset);
color += SAMPLE_TEXTURE2D_X(_MainTex, sampler_MainTex, input.uv + float2( 1,-1) * offset);
color += SAMPLE_TEXTURE2D_X(_MainTex, sampler_MainTex, input.uv + float2(-1,-1) * offset);

return color/5.0;
}

ENDHLSL

Pass
{
HLSLPROGRAM

#pragma vertex Vert
#pragma fragment Frag

ENDHLSL
}
}
}

рдХреНрдпреЛрдВ рдирд╣реАрдВ ShaderGraph?
ShaderGraph , 13 :)

OutlineFeature рдореЗрдВ рдПрдХ рдорд╛рд░реНрдЧ рдЬреЛрдбрд╝реЗрдВ


рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣рдорд╛рд░реЗ рдкрд╣рд▓реЗ рдкрд╛рд╕ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд╕рдорд╛рди рд╣реЛрдЧреАред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдмрдирд╛рдПрдВред

    [Serializable]
    public class BlurSettings
    {
        public Material BlurMaterial;
        public int DownSample = 1;
        public int PassesCount = 1;
    }

рдлрд┐рд░ рдЦреЗрддред

[SerializeField] private string _bluredTextureName;
[SerializeField] private BlurSettings _blurSettings;
private RenderTargetHandle _bluredTexture;
private BlurPass _blurPass;

...

public override void Create()
{
    _bluredTexture.Init(_bluredTextureName);

    _blurPass = new BlurPass(_blurSettings.BlurMaterial, _blurSettings.DownSample, _blurSettings.PassesCount);
}

рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдХрддрд╛рд░ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
    renderer.EnqueuePass(_renderPass);
    renderer.EnqueuePass(_blurPass);
}

рдкрд╛рд╕ рдкрд░рд┐рдгрд╛рдо:


рдЖрдЙрдЯрд▓рд╛рдЗрди рдкрд╛рд╕


рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕реНрдЯреНрд░реЛрдХ рдХреЗ рд╕рд╛рде рдЕрдВрддрд┐рдо рдЫрд╡рд┐ рдХреЛ shader рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдФрд░ рдЙрд╕рдХреЗ рдХрд╛рд░реНрдп рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╕реНрдХреНрд░реАрди рдкрд░ рд╡рд░реНрддрдорд╛рди рдЫрд╡рд┐ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдЧрд╛ред

рдиреАрдЪреЗ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдкреВрд░рд╛ рдкрд╛рд╕ рдХреЛрдб рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рд╕рднреА рддрд░реНрдХ рджреЛ рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рд╣реИрдВред

public class OutlinePass : ScriptableRenderPass
{
    private string _profilerTag = "Outline";
    private Material _material;

    public OutlinePass(Material material)
    {
        _material = material;
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        var cmd = CommandBufferPool.Get(_profilerTag);

        using (new ProfilingSample(cmd, _profilerTag))
        {
            var mesh = RenderingUtils.fullscreenMesh;
            cmd.DrawMesh(mesh, Matrix4x4.identity, _material, 0, 0);
        }

        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
}

RenderingUtils.fullscreenMesh рдПрдХ 1 рд╕реЗ 1 рдЬрд╛рд▓ рджреЗрддрд╛ рд╣реИред

рд╢реЗрдбрд░


рд░реВрдкрд░реЗрдЦрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ shader рдмрдирд╛рдПрдБред рдЗрд╕рдореЗрдВ рджреЛ рд╡реИрд╢реНрд╡рд┐рдХ рдмрдирд╛рд╡рдЯ рдЧреБрдг рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред _OutlineRenderTexture рдФрд░ _OutlineBluredTexture рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рдЫрд╡рд┐ рдФрд░ рдЗрд╕рдХреЗ рдзреБрдВрдзрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдПред

shader рдХреЛрдб
Shader "Custom/Outline"
{
    Properties
    {
        _Color ("Glow Color", Color ) = ( 1, 1, 1, 1)
        _Intensity ("Intensity", Float) = 2
        [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1
        [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 0
    }
    
    SubShader
    {       
        HLSLINCLUDE
 
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        
        struct Attributes
        {
            float4 positionOS   : POSITION;
            float2 uv           : TEXCOORD0;
        };
        
        struct Varyings
        {
            half4 positionCS    : SV_POSITION;
            half2 uv            : TEXCOORD0;
        };
 
        TEXTURE2D_X(_OutlineRenderTexture);
        SAMPLER(sampler_OutlineRenderTexture);
 
        TEXTURE2D_X(_OutlineBluredTexture);
        SAMPLER(sampler_OutlineBluredTexture);
 
        half4 _Color;
        half _Intensity;
 
        Varyings Vertex(Attributes input)
        {
            Varyings output;
            output.positionCS = float4(input.positionOS.xy, 0.0, 1.0); 
            output.uv = input.uv;
            if (_ProjectionParams.x < 0.0) 
                output.uv.y = 1.0 - output.uv.y;    
            return output;      
        }
 
        half4 Fragment(Varyings input) : SV_Target
        {
            float2 uv = UnityStereoTransformScreenSpaceTex(input.uv);
            half4 prepassColor = SAMPLE_TEXTURE2D_X(_OutlineRenderTexture, sampler_OutlineRenderTexture, uv);
            half4 bluredColor = SAMPLE_TEXTURE2D_X(_OutlineBluredTexture, sampler_OutlineBluredTexture,uv);
            half4 difColor = max( 0, bluredColor - prepassColor);
            half4 color = difColor* _Color * _Intensity;
            color.a = 1;    
            return color;
        }
        
        ENDHLSL        
     
        Pass
        {
            Blend [_SrcBlend] [_DstBlend]
            ZTest Always    //  ,      
            ZWrite Off      //      
            Cull Off        //    
 
            HLSLPROGRAM
           
            #pragma vertex Vertex
            #pragma fragment Fragment        
 
            ENDHLSL         
        }
    }
}

, . Unity . , _ProjectionParams..

рджреЛ рдкрд╣рд▓реЗ рдкреНрд░рд╛рдкреНрдд рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП shader рдХрд╛ рдкрд░рд┐рдгрд╛рдо:



OutlineFeature рдореЗрдВ рдПрдХ рдорд╛рд░реНрдЧ рдЬреЛрдбрд╝реЗрдВ


рд╕рднреА рдХреНрд░рд┐рдпрд╛рдПрдВ рдкрд┐рдЫрд▓реЗ рдкрд╛рд╕ рдХреЗ рд╕рдорд╛рди рд╣реИрдВред

[SerializeField] private Material _outlineMaterial;
private OutlinePass _outlinePass;

public override void Create()
{
    ...
    _outlinePass = new OutlinePass(_outlineMaterial);
    ....
}

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
    renderer.EnqueuePass(_renderPass);
    renderer.EnqueuePass(_blurPass);
    renderer.EnqueuePass(_outlinePass);
}

RenderPassEvent


рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИ рдХрд┐ рдирд┐рд░реНрдорд┐рдд рдкрд╛рд╕ рдХрдм рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ renderPassEvent рдкреИрд░рд╛рдореАрдЯрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

рдШрдЯрдирд╛ рд╕реВрдЪреА
Universal RP, .
BeforeRendering
BeforeRenderingShadows
AfterRenderingShadows
BeforeRenderingPrepasses
AfterRenderingPrePasses
BeforeRenderingOpaques
AfterRenderingOpaques
BeforeRenderingSkybox
AfterRenderingSkybox
BeforeRenderingTransparents
AfterRenderingTransparents
BeforeRenderingPostProcessing
AfterRenderingPostProcessing
AfterRendering

OutlineFeature рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рдлрд╝реАрд▓реНрдб рдмрдирд╛рдПрдБред

[SerializeField] private RenderPassEvent _renderPassEvent;

рдФрд░ рд╣рдо рдЗрд╕реЗ рд╕рднреА рдмрдирд╛рдП рдЧрдП рдорд╛рд░реНрдЧ рд╕реЗ рд╕рдВрдХреЗрдд рджреЗрдВрдЧреЗред

public override void Create()
{
    ...
    _renderPass.renderPassEvent = _renderPassEvent;
    _blurPass.renderPassEvent = _renderPassEvent;
    _outlinePass.renderPassEvent = _renderPassEvent;
}

рдЕрдиреБрдХреВрд▓рди


рдПрдХ рдЖрдЙрдЯрд▓рд╛рдЗрди рд▓реЗрдпрд░ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЗрд╕реЗ рдЙрди рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯ рдХрд░реЗрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо рд╕рд░реНрдХрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рд╣рдо рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдкрддреНрддрд┐ рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗ: UniversalRendererPipelineAsset рдФрд░ ForwardRendererDataред



рдкрд░рд┐рдгрд╛рдо


рд╣рдорд╛рд░реЗ рдореВрд▓ рдлреНрд░реЗрдо рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдгрд╛рдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реЛрдЧрд╛!



рд╕рдорд╛рдкрди


рдЕрдм рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд░реВрдкрд░реЗрдЦрд╛ рд╣рдореЗрд╢рд╛ рдЕрдиреНрдп рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреА рджрд┐рдЦрд╛рдИ рджреЗрдЧреАред рд╣рдорд╛рд░реЗ рдкреНрд░рднрд╛рд╡ рдХреЛ рджреГрд╢реНрдп рдХреА рдЧрд╣рд░рд╛рдИ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдИ рдмрджрд▓рд╛рд╡ рдХрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдПред

RenderObjectsPass


рд╣рдорд╛рд░реЗ рд░реЗрдВрдбрд░ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╕рдордп, рд╣рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдЧрд╣рд░рд╛рдИ рдмрдлрд░ рдХреЛ рднреА рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЙрдкрдпреБрдХреНрдд рдлрд╝реАрд▓реНрдб рдФрд░ рд╡рд┐рдзрд┐ рдмрдирд╛рдПрдБред

public class MyRenderObjectsPass : ScriptableRenderPass
{
    ...
    private RenderTargetIdentifier _depth;

    public void SetDepthTexture(RenderTargetIdentifier depth)
    { _depth = depth; }
    ...
}

рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ () рд╡рд┐рдзрд┐ рдореЗрдВ, рд░реЗрдВрдбрд░ рд▓рдХреНрд╖реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдЧрд╣рд░рд╛рдИ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред

public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
    cmd.GetTemporaryRT(_destination.id, cameraTextureDescriptor);
    ConfigureTarget(_destination.Identifier(), _depth);
    ConfigureClear(ClearFlag.Color, Color.clear);
}

Outlinefeature


рдмрд╛рд╣реНрдпрд░реЗрдЦрд╛ рдореЗрдВ, рд╣рдо MyRenderObjectsPass рдХреЛ рд╡рд░реНрддрдорд╛рди рджреГрд╢реНрдп рдЧрд╣рд░рд╛рдИ рд╕реЗ рдкрд╛рд╕ рдХрд░реЗрдВрдЧреЗред

public class OutlineFeature : ScriptableRendererFeature
{
    ...
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        var depthTexture = renderer.cameraDepth;
        _renderPass.SetDepthTexture(depthTexture);

        renderer.EnqueuePass(_renderPass);
        renderer.EnqueuePass(_blurPass);
        renderer.EnqueuePass(_outlinePass);
    }
    ...
}

UniversalRenderPipelineAsset


рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП UniversalRenderPipelineAset рдореЗрдВ, DepthTexture рдХреЗ рдмрдЧрд▓ рдореЗрдВ рд╕реНрдерд┐рдд рдмреЙрдХреНрд╕ рдХреЛ рдЪреЗрдХ рдХрд░реЗрдВред


рдкрд░рд┐рдгрд╛рдо


рдЧрд╣рд░рд╛рдИ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдкрд░рд┐рдгрд╛рдо:


рдЧрд╣рд░рд╛рдИ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкрд░рд┐рдгрд╛рдо:



рд╕рдВрдкреВрд░реНрдг


ScriptableRendererFeature рдЖрдкрдХреЗ рдорд╛рд░реНрдЧ рдХреЛ RP рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЙрдкрдХрд░рдг рд╣реИред
рдЗрд╕рдореЗрдВ, рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ RenderObjectsPass рдХреА рдЬрдЧрд╣ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдиреНрдп ScriptableRendererFeature рдореЗрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдкрдХреЛ рдпреВрдирд┐рд╡рд░реНрд╕рд▓ RP рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЬрд╛рдиреЗ рдФрд░ рдХреБрдЫ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рдХреЛрдб рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

рдкреБрдирд╢реНрдЪ


ScriptableRendererFeature рдФрд░ ScriptableRenderPass рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рд╕рд╛рдорд╛рдиреНрдп рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдФрд░ рддрд╛рдХрд┐ рд▓реЗрдЦ рдмрд╣реБрдд рдЕрдзрд┐рдХ рди рдмрдврд╝реЗ, рдореИрдВрдиреЗ рдЬрд╛рдирдмреВрдЭрдХрд░ рдкрд╛рд╕ рдХреЛрдб рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЙрдирдХреА рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХрддрд╛ рдФрд░ рдЗрд╖реНрдЯрддрдорддрд╛ рдХреА рднреАред

рд╕рдВрджрд░реНрдн


рд╕реНрд░реЛрдд рдХреЛрдб gitlab рдХрд╛ рдПрдХ рд▓рд┐рдВрдХ рд╣реИред
рдореЙрдбрд▓ рдФрд░ рджреГрд╢реНрдп рд▓реИрдВрдбрд░ рдорд┐рд╢рдиреЛрдВ рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдЧреНрд░рд╣ рдЧрд╣рд░рд╛рдИ рдХрд╛ рдЦреЗрд▓ред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрдЯреНрд░реЛрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ - рдпреВрдЯреНрдпреВрдм рд▓рд┐рдВрдХ
рдпреВрдирд┐рдЯреА рдХрд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рд░реЗрдВрдбрд░рдлрд╝рд╛рдЗрдЯрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрджрд╛рд╣рд░рдг - рдЬреАрдердм рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ ред

рдЕрдкрдиреА рдЦреБрдж рдХреА ScriptableRenderPipeline рдмрдирд╛рдиреЗ рдкрд░ рдкрд╛рдареЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ред рдЖрд░рдкреА рдФрд░ рд╢реЗрдбрд░реНрд╕ рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рддрд░реНрдХ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж, рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХрд╛ рд▓рд┐рдВрдХ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ ред

All Articles