Création d'un effet de contour dans Unity Universal Render Pipeline

Dans l'Universal Render Pipeline, en créant votre propre RendererFeature, vous pouvez facilement étendre les capacités de rendu. L'ajout de nouvelles passes au pipeline de rendu vous permet de créer divers effets. Dans cet article, à l'aide de ScriptableRendererFeature et ScriptableRenderPass, nous allons créer l'effet Outline de l'objet et considérer certaines fonctionnalités de son implémentation.

Effet de contour


Introduction ou quelques mots sur Render Pipeline


Scriptable Render Pipeline vous permet de contrôler le rendu des graphiques via des scripts en C # et de contrôler l'ordre de traitement des objets, des lumières, des ombres, etc. Universal Render Pipeline est un pipeline de rendu scriptable prêt à l'emploi développé par Unity et conçu pour remplacer l'ancien RP intégré.

Les capacités d'Universal RP peuvent être étendues en créant et en ajoutant vos propres passes de dessin (ScriptableRendererFeature et ScriptableRenderPass). Ce sera l'article actuel. Il sera utile à ceux qui vont passer à Universal RP et, peut-être, aidera à mieux comprendre le travail de ScriptableRenderPass'ov existant dans Universal RP.

Cet article a été écrit dans Unity 2019.3 et Universal RP 7.1.8.

Plan d'action


Nous allons comprendre comment ScriptableRendererFeature et ScriptableRenderPass fonctionnent sur l'exemple de création de l'effet de trait des objets opaques.

Pour ce faire, créez un ScriptableRendererFeature qui effectue les actions suivantes:

  • dessin d'objets spĂ©cifiĂ©s
  • brouiller les objets dessinĂ©s
  • obtention de contours d'objets Ă  partir d'images obtenues lors de passes prĂ©cĂ©dentes

Trame source -

Et la séquence de résultats que nous devons atteindre:


Au cours du travail, nous allons créer un shader, dans les propriétés globales dont les résultats des première et deuxième passes seront sauvegardés. Le dernier passage affichera le résultat du shader lui-même sur l'écran.

Propriétés globales
, , Properties. — .

— . .

Créer un contour


ScriptableRendererFeature est utilisé pour ajouter des passages de rendu personnalisés (ScriptableRenderPass) à Universal RP. Créez une classe OutlineFeature qui hérite de ScriptableRenderFeature et implémentez ses méthodes.

using UnityEngine;
using UnityEngine.Rendering.Universal;

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

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

La méthode Create () est utilisée pour créer et configurer des passes. Et la méthode AddRenderPasses () pour injecter les passes créées dans la file d'attente de rendu.

arguments AddRenderPasses ()
ScriptableRenderer — Universal RP. Universal RP Forward Rendering.

RenderingData — , , .

Commençons maintenant à créer les passes de rendu, et nous reviendrons à la classe actuelle après avoir implémenté chacune d'elles.

Les objets de rendu passent


La tâche de ce passage est de dessiner des objets à partir d'une couche spécifique avec le remplacement du matériau dans la propriété de texture globale du shader. Ce sera une version simplifiée du passage RenderObjectsPass disponible dans Universal RP, avec la seule différence dans la cible (RenderTarget) où le rendu sera effectué.

Créez une classe MyRenderObjectsPass héritée de ScriptableRenderPass. Nous implémentons la méthode Execute (), qui contiendra toute la logique du passage, ainsi que redéfinissons la méthode Configure ().

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)
        { }
    }
}

La méthode Configure () est utilisée pour spécifier le but du rendu et de la création de textures temporaires. Par défaut, la cible est la cible de la caméra actuelle, et après avoir terminé la passe, elle sera de nouveau indiquée par défaut. Cette méthode est appelée avant l'exécution de la logique de base.

Remplacement de la cible de rendu


Déclarez un RenderTargetHandle pour une nouvelle cible de rendu. En l'utilisant, créez une texture temporaire et indiquez-la comme cible. RenderTargetHandle contient l'identifiant de la RenderTexture temporaire utilisée. Il vous permet également d'obtenir un RenderTargetIdentifier, qui est utilisé pour identifier une cible de rendu qui peut être définie, par exemple, comme RenderTexture, objet Texture, RenderTexture temporaire ou intégré (utilisé par la caméra lors du rendu d'un cadre).

Un objet RenderTargetHandle sera créé dans OutlineFeature et transmis à notre passe lors de sa création.

private RenderTargetHandle _destination;

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

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

La méthode GetTemporaryRT () crée une RenderTexture temporaire avec les paramètres spécifiés et la définit comme une propriété globale de shader avec le nom spécifié (le nom sera défini dans la fonction).

Supprimer RenderTexture
ReleaseTemporaryRT() RenderTexture. Execute() FrameCleanup.
, RenderTexture, , .

Pour créer une texture de rendu temporaire, nous utilisons le descripteur de la caméra actuelle contenant des informations sur la taille, le format et d'autres paramètres de la cible de la caméra.

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

Le but de la cible et son nettoyage ne doivent se produire que dans Configure () à l'aide des méthodes ConfigureTarget () et ClearTarget ().

Rendre


Nous ne considérerons pas le rendu en détail, car cela peut nous éloigner de très loin du sujet principal. Pour le rendu, nous utiliserons la méthode ScriptableRenderContext.DrawRenderers (). Créez des paramètres pour rendre uniquement les objets opaques uniquement à partir des calques spécifiés. Le masque de calque sera transmis au constructeur.

...
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);
}

Très brièvement sur les paramètres
CullingResults — ( RenderingData)
FilteringSettings — .
DrawingSettings — .
RenderStateBlock — , (, ..)

À propos du RenderObjectsPass terminé dans UniversalRP
, . . RenderObjectsPass, Universal RP, . RenderFeature - :)

Remplacement du matériel


Nous redéfinissons les matériaux utilisés pour le rendu, car nous n'avons besoin que des contours des objets.

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;
...
}

Shader pour le rendu


Créez un shader de matériau dans ShaderGraph qui sera utilisé lors du dessin d'objets dans la passe actuelle.


Ajouter un passage Ă  OutlineFeature


Retour à OutlieFeature. Tout d'abord, créez une classe pour les paramètres de notre passage.

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

Déclarez les champs pour les paramètres MyRenderPass et le nom de la propriété de texture globale utilisée comme cible de rendu par notre passe.

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

Créez un identifiant pour la propriété de texture et une instance de MyRenderPass.

private RenderTargetHandle _renderTexture;
private MyRenderObjectsPass _renderPass;

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

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

Dans la méthode AddRendererPass, nous ajoutons notre passe à la file d'attente d'exécution.

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

Regarder vers l'avant
. , .

Le résultat de la passe pour la scène source doit être le suivant:


DĂ©bogage
Frame Debug (Windows-Analysis-FrameDebugger).

Passe de flou


Le but de ce passage est de brouiller l'image obtenue à l'étape précédente et de la définir sur la propriété de shader global.

Pour ce faire, nous allons copier la texture d'origine plusieurs fois dans une texture temporaire, en utilisant le shader de flou dessus. Dans ce cas, l'image originale peut être réduite (créer une copie réduite), ce qui accélérera les calculs et n'affectera pas la qualité du résultat.

Créons la classe BlurPass héritée de ScriptableRenderPass.

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

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

Obtenons les variables pour les textures source, cible et temporaires (et leur ID).

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

private RenderTargetIdentifier _tmpBlurRT1;
private RenderTargetIdentifier _tmpBlurRT2;

private RenderTargetIdentifier _source;
private RenderTargetHandle _destination;

Tous les ID pour RenderTexture sont définis via Shader.PropertyID (). Cela ne signifie pas que quelque part de telles propriétés de shader doivent nécessairement exister.

Ajoutez des champs pour les paramètres restants, que nous initialisons immédiatement dans le constructeur.

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

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

_blurMaterial - matériau avec un shader de flou.
_downSample - coefficient pour réduire la taille de la texture
_passesCount - le nombre de passes de flou Ă  appliquer.

Pour créer des textures temporaires, créez un descripteur avec toutes les informations nécessaires à ce sujet - taille, format et plus encore. La hauteur et la taille seront mises à l'échelle par rapport au descripteur de la caméra.

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);
Nous allons également créer les identifiants et la texture de rendu temporaire eux-mêmes.
    _tmpBlurRT1 = new RenderTargetIdentifier(_tmpBlurRTId1);
    _tmpBlurRT2 = new RenderTargetIdentifier(_tmpBlurRTId2);

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

Nous modifions à nouveau la cible de rendu, alors créez une autre texture temporaire et spécifiez-la comme cible.

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

Brouiller


Certaines tâches de rendu peuvent être effectuées à l'aide de méthodes spéciales ScriptableRenderContext qui lui configurent et lui ajoutent des commandes. Pour exécuter d'autres commandes, vous devrez utiliser le CommandBuffer, qui peut être obtenu à partir du pool.
Après avoir ajouté des commandes et les avoir envoyées au contexte, le tampon devra être renvoyé au pool.

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

L'implémentation finale de la méthode Execute () sera la suivante.

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


Pour flouter, créez un shader simple qui calculera la couleur du pixel en tenant compte de ses voisins les plus proches (la valeur de couleur moyenne de cinq pixels).

Ombrage de flou
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
}
}
}

Pourquoi pas ShaderGraph?
ShaderGraph , 13 :)

Ajouter un passage Ă  OutlineFeature


La procédure sera similaire à l'ajout de notre première passe. Créez d'abord les paramètres.

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

Puis les champs.

[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);
}

Et ajoutez à la file d'attente pour l'exécution.

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

Résultat de réussite:


Pass contour


L'image finale avec le trait des objets sera obtenue à l'aide du shader. Et le résultat de son travail sera affiché en haut de l'image actuelle à l'écran.

Vous trouverez ci-dessous le code d'accès complet à la fois, comme toute logique est sur deux lignes.

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 renvoie un maillage 1 par 1.

Shader


Créez un shader pour obtenir le contour. Il doit contenir deux propriétés de texture globales. _OutlineRenderTexture et _OutlineBluredTexture pour l'image des objets spécifiés et sa version floue.

code de 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..

Le résultat du shader pour deux images précédemment obtenues:



Ajouter un passage Ă  OutlineFeature


Toutes les actions sont similaires aux passes précédentes.

[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


Il reste à indiquer quand les passes créées seront appelées. Pour ce faire, chacun d'eux doit spécifier le paramètre renderPassEvent.

Liste des événements
Universal RP, .
BeforeRendering
BeforeRenderingShadows
AfterRenderingShadows
BeforeRenderingPrepasses
AfterRenderingPrePasses
BeforeRenderingOpaques
AfterRenderingOpaques
BeforeRenderingSkybox
AfterRenderingSkybox
BeforeRenderingTransparents
AfterRenderingTransparents
BeforeRenderingPostProcessing
AfterRenderingPostProcessing
AfterRendering

Créez le champ approprié dans OutlineFeature.

[SerializeField] private RenderPassEvent _renderPassEvent;

Et nous l'indiquerons à tous les passages créés.

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

Personnalisation


Ajoutez un calque de contour et définissez-le pour les objets que vous souhaitez encercler.

Nous allons créer et configurer tous les actifs nécessaires: UniversalRendererPipelineAsset et ForwardRendererData.



RĂ©sultat


Le résultat pour notre cadre d'origine sera le suivant!



Achèvement


Désormais, le contour de l'objet sera toujours visible, même à travers d'autres objets. Pour que notre effet prenne en compte la profondeur de la scène, plusieurs modifications doivent être apportées.

RenderObjectsPass


Lorsque vous spécifiez le but de notre rendu, nous devons également indiquer le tampon de profondeur actuel. Créez le champ et la méthode appropriés.

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

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

Dans la méthode Configure (), spécifiez la profondeur de définition de la cible de rendu.

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

Fonctionnalité


Dans OutlineFeature, nous transmettrons MyRenderObjectsPass la profondeur de scène actuelle.

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


Dans le UniversalRenderPipelineAsset utilisé, cochez la case en regard de DepthTexture.


RĂ©sultat


RĂ©sultat hors profondeur:


Résultat basé sur la profondeur:



Total


ScriptableRendererFeature est un outil assez pratique pour ajouter vos passages au RP.
Dans celui-ci, vous pouvez facilement remplacer les RenderObjectsPass et les utiliser dans d'autres ScriptableRendererFeature. Vous n'avez pas besoin d'approfondir la mise en Ĺ“uvre de Universal RP et de modifier son code pour ajouter quelque chose.

PS


Afin de rendre plus clair l'algorithme général de travail avec ScriptableRendererFeature et ScriptableRenderPass, et afin que l'article ne se développe pas trop, j'ai intentionnellement essayé de créer un code d'accès simple, même au détriment de leur universalité et de leur optimalité.

Références


Le code source est un lien vers gitlab. Les
modèles et la scène sont tirés du jeu Lander Missions: planet depths.
L'implémentation de l'AVC suivante a été prise comme base de l'exemple - lien youtube
propres exemples d'implémentation RenderFeature d'Unity - lien vers github .

Une série de leçons sur la création de votre propre ScriptableRenderPipeline. Après avoir lu la logique générale du RP et des shaders, le lien vers les tutoriels devient clair .

All Articles