< Summary

Class:OutlineMaskFeature
Assembly:Outliner
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/Outliner/OutlineMaskFeature.cs
Covered lines:9
Uncovered lines:89
Coverable lines:98
Total lines:220
Line coverage:9.1% (9 of 98)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
OutlinerRenderPass()0%2100%
OutlinerRenderPass(...)0%110100%
Setup(...)0%2100%
Configure(...)0%2100%
Execute(...)0%6200%
DrawRenderers(...)0%42600%
DrawAvatar(...)0%42600%
CopyAvatarProperties(...)0%1821300%
FrameCleanup(...)0%6200%
Create()0%110100%
AddRenderPasses(...)0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/Outliner/OutlineMaskFeature.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Linq;
 3using UnityEngine;
 4using UnityEngine.Rendering;
 5using UnityEngine.Rendering.Universal;
 6
 7public class OutlineMaskFeature : ScriptableRendererFeature
 8{
 9    private class OutlinerRenderPass : ScriptableRenderPass
 10    {
 11        private const int DEPTH_BUFFER_BITS = 0;
 12        private const string PROFILER_TAG = "Outliner Mask Pass";
 13        private const bool USE_BASE_MATERIAL = false; // Use the material in the renderer and look for an "Outliner" pas
 14
 015        private static readonly int BONE_MATRICES = Shader.PropertyToID("_Matrices");
 016        private static readonly int BIND_POSES = Shader.PropertyToID("_BindPoses");
 017        private static readonly int RENDERER_WORLD_INVERSE = Shader.PropertyToID("_WorldInverse");
 018        private static readonly int AVATAR_MAP1 = Shader.PropertyToID("_AvatarMap1");
 019        private static readonly int AVATAR_MAP2 = Shader.PropertyToID("_AvatarMap2");
 020        private static readonly int AVATAR_MAP3 = Shader.PropertyToID("_AvatarMap3");
 021        private static readonly int AVATAR_MAP4 = Shader.PropertyToID("_AvatarMap4");
 022        private static readonly int AVATAR_MAP5 = Shader.PropertyToID("_AvatarMap5");
 023        private static readonly int AVATAR_MAP6 = Shader.PropertyToID("_AvatarMap6");
 024        private static readonly int AVATAR_MAP7 = Shader.PropertyToID("_AvatarMap7");
 025        private static readonly int AVATAR_MAP8 = Shader.PropertyToID("_AvatarMap8");
 026        private static readonly int AVATAR_MAP9 = Shader.PropertyToID("_AvatarMap9");
 027        private static readonly int AVATAR_MAP10 = Shader.PropertyToID("_AvatarMap10");
 028        private static readonly int AVATAR_MAP11 = Shader.PropertyToID("_AvatarMap11");
 029        private static readonly int AVATAR_MAP12 = Shader.PropertyToID("_AvatarMap12");
 30
 31        private readonly OutlineRenderersSO outlineRenderersSo;
 32        private readonly Material material;
 33        private readonly Material gpuSkinningMaterial;
 34
 35        private RenderTargetHandle outlineTextureHandle;
 36        private RenderTextureDescriptor descriptor;
 37
 238        private readonly List<Material> toDispose = new List<Material>();
 39
 240        public OutlinerRenderPass(OutlineRenderersSO outlineRenderersSo)
 41        {
 242            material = CoreUtils.CreateEngineMaterial("Hidden/DCL/OutlineMaskPass");
 243            gpuSkinningMaterial = CoreUtils.CreateEngineMaterial("Hidden/DCL/OutlineGPUSkinningMaskPass");
 244            this.outlineRenderersSo = outlineRenderersSo;
 245        }
 46
 47        public void Setup(RenderTextureDescriptor descriptor, RenderTargetHandle outlineTextureHandle)
 48        {
 049            this.outlineTextureHandle = outlineTextureHandle;
 050            descriptor.colorFormat = RenderTextureFormat.ARGB32;
 051            descriptor.depthBufferBits = DEPTH_BUFFER_BITS;
 052            this.descriptor = descriptor;
 053        }
 54
 55        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
 56        {
 57            //Configure CommandBuffer to output the mask result in the provided texture
 058            cmd.GetTemporaryRT(outlineTextureHandle.id, descriptor, FilterMode.Point);
 059            ConfigureTarget(outlineTextureHandle.Identifier());
 060            ConfigureClear(ClearFlag.All, Color.black);
 061        }
 62
 63        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
 64        {
 065            CommandBuffer cmd = CommandBufferPool.Get(PROFILER_TAG);
 66
 067            using (new ProfilingScope(cmd, new ProfilingSampler(PROFILER_TAG)))
 68            {
 069                context.ExecuteCommandBuffer(cmd);
 070                cmd.Clear();
 71
 072                if (outlineRenderersSo != null)
 73                {
 74                    //By now only outline avatars
 75                    //DrawRenderers(outlineRenderersSo?.renderers, renderingData.cameraData.camera.cullingMask, cmd);
 076                    DrawAvatar(outlineRenderersSo.avatar, renderingData.cameraData.camera.cullingMask, cmd);
 77                }
 78
 079                cmd.SetGlobalTexture("_OutlineTexture", outlineTextureHandle.id);
 080            }
 81
 082            context.ExecuteCommandBuffer(cmd);
 083            CommandBufferPool.Release(cmd);
 084        }
 85
 86        private void DrawRenderers(List<(Renderer renderer, int meshCount)> renderers, int cameraCulling, CommandBuffer 
 87        {
 088            if (renderers == null)
 089                return;
 90
 091            foreach ((Renderer renderer, int meshCount) in renderers)
 92            {
 93                //Ignore disabled renderers
 094                if (!renderer.gameObject.activeSelf || (cameraCulling & (1 << renderer.gameObject.layer)) == 0)
 95                    continue;
 96
 97                // We have to manually render all the submeshes of the selected objects.
 098                for (var i = 0; i < meshCount; i++) { cmd.DrawRenderer(renderer, material, i); }
 99            }
 0100        }
 101
 102        private void DrawAvatar((Renderer renderer, int meshCount, float avatarHeight) avatar, int cameraCulling, Comman
 103        {
 0104            if (avatar.renderer == null)
 0105                return;
 106
 107            //Ignore disabled or culled by camera avatars
 0108            if (!avatar.renderer.gameObject.activeSelf || (cameraCulling & (1 << avatar.renderer.gameObject.layer)) == 0
 0109                return;
 110
 0111            for (var i = 0; i < avatar.meshCount; i++)
 112            {
 0113                Material materialToUse = null;
 114
 115                // We use a GPU Skinning based material
 0116                if (avatar.renderer.materials[i] != null)
 117                {
 118                    //Enable it when we are capable of adding the pass into the Toon Shader
 119                    if (USE_BASE_MATERIAL)
 120                    {
 121                        int originalMaterialOutlinerPass = avatar.renderer.materials[i].FindPass("Outliner");
 122
 123                        if (originalMaterialOutlinerPass != -1)
 124                        {
 125                            //The material has a built in pass we can use
 126                            cmd.DrawRenderer(avatar.renderer, avatar.renderer.materials[i], i, originalMaterialOutlinerP
 127                            continue;
 128                        }
 129                    }
 130
 131                    // We use the original material to copy the GPUSkinning values.
 132                    // We cannot use materialToUse.CopyPropertiesFromMaterial because there are non serialized uniforms 
 0133                    materialToUse = new Material(gpuSkinningMaterial);
 0134                    toDispose.Add(materialToUse);
 0135                    CopyAvatarProperties(avatar.renderer.materials[i], materialToUse);
 136                }
 137                else // Fallback to the normal outliner without GPUSkinning
 138                {
 0139                    materialToUse = material;
 140                }
 141
 142                // We have to manually render all the submeshes of the selected objects.
 0143                cmd.DrawRenderer(avatar.renderer, materialToUse, i);
 144            }
 0145        }
 146
 147        private void CopyAvatarProperties(Material source, Material target)
 148        {
 0149            target.SetMatrixArray(BIND_POSES, source.GetMatrixArray(BIND_POSES));
 0150            target.SetMatrix(RENDERER_WORLD_INVERSE, source.GetMatrix(RENDERER_WORLD_INVERSE));
 0151            target.SetMatrixArray(BONE_MATRICES, source.GetMatrixArray(BONE_MATRICES));
 152
 0153            if (source.HasTexture(AVATAR_MAP1))
 0154                target.SetTexture(AVATAR_MAP1, source.GetTexture(AVATAR_MAP1));
 155
 0156            if (source.HasTexture(AVATAR_MAP2))
 0157                target.SetTexture(AVATAR_MAP2, source.GetTexture(AVATAR_MAP2));
 158
 0159            if (source.HasTexture(AVATAR_MAP3))
 0160                target.SetTexture(AVATAR_MAP3, source.GetTexture(AVATAR_MAP3));
 161
 0162            if (source.HasTexture(AVATAR_MAP4))
 0163                target.SetTexture(AVATAR_MAP4, source.GetTexture(AVATAR_MAP4));
 164
 0165            if (source.HasTexture(AVATAR_MAP5))
 0166                target.SetTexture(AVATAR_MAP5, source.GetTexture(AVATAR_MAP5));
 167
 0168            if (source.HasTexture(AVATAR_MAP6))
 0169                target.SetTexture(AVATAR_MAP6, source.GetTexture(AVATAR_MAP6));
 170
 0171            if (source.HasTexture(AVATAR_MAP7))
 0172                target.SetTexture(AVATAR_MAP7, source.GetTexture(AVATAR_MAP7));
 173
 0174            if (source.HasTexture(AVATAR_MAP8))
 0175                target.SetTexture(AVATAR_MAP8, source.GetTexture(AVATAR_MAP8));
 176
 0177            if (source.HasTexture(AVATAR_MAP9))
 0178                target.SetTexture(AVATAR_MAP9, source.GetTexture(AVATAR_MAP9));
 179
 0180            if (source.HasTexture(AVATAR_MAP10))
 0181                target.SetTexture(AVATAR_MAP10, source.GetTexture(AVATAR_MAP10));
 182
 0183            if (source.HasTexture(AVATAR_MAP11))
 0184                target.SetTexture(AVATAR_MAP11, source.GetTexture(AVATAR_MAP11));
 185
 0186            if (source.HasTexture(AVATAR_MAP12))
 0187                target.SetTexture(AVATAR_MAP12, source.GetTexture(AVATAR_MAP12));
 0188        }
 189
 190        public override void FrameCleanup(CommandBuffer cmd)
 191        {
 0192            cmd.ReleaseTemporaryRT(outlineTextureHandle.id);
 193
 0194            for (var index = 0; index < toDispose.Count; index++) { Object.Destroy(toDispose[index]); }
 195
 0196            toDispose.Clear();
 0197        }
 198    }
 199
 200    public OutlineRenderersSO renderers;
 201    private OutlinerRenderPass scriptablePass;
 202
 203    private RenderTargetHandle outlineTexture;
 204
 205    public override void Create()
 206    {
 2207        scriptablePass = new OutlinerRenderPass(renderers)
 208        {
 209            renderPassEvent = RenderPassEvent.AfterRenderingTransparents,
 210        };
 211
 2212        outlineTexture.Init("_OutlineTexture");
 2213    }
 214
 215    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
 216    {
 0217        scriptablePass.Setup(renderingData.cameraData.cameraTargetDescriptor, outlineTexture);
 0218        renderer.EnqueuePass(scriptablePass);
 0219    }
 220}