< Summary

Class:OutlineMaskFeature
Assembly:Outliner
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/Outliner/OutlineMaskFeature.cs
Covered lines:9
Uncovered lines:85
Coverable lines:94
Total lines:217
Line coverage:9.5% (9 of 94)
Covered branches:0
Total branches:0
Covered methods:2
Total methods:11
Method coverage:18.1% (2 of 11)

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
 67            //using (new ProfilingScope(cmd, new ProfilingSampler(PROFILER_TAG)))
 68            {
 069                if (outlineRenderersSo != null)
 70                {
 71                    //By now only outline avatars
 72                    //DrawRenderers(outlineRenderersSo?.renderers, renderingData.cameraData.camera.cullingMask, cmd);
 073                    DrawAvatar(outlineRenderersSo.avatar, renderingData.cameraData.camera.cullingMask, cmd);
 74                }
 75
 076                cmd.SetGlobalTexture("_OutlineTexture", outlineTextureHandle.id);
 77            }
 78
 079            context.ExecuteCommandBuffer(cmd);
 080            CommandBufferPool.Release(cmd);
 081        }
 82
 83        private void DrawRenderers(List<(Renderer renderer, int meshCount)> renderers, int cameraCulling, CommandBuffer 
 84        {
 085            if (renderers == null)
 086                return;
 87
 088            foreach ((Renderer renderer, int meshCount) in renderers)
 89            {
 90                //Ignore disabled renderers
 091                if (!renderer.gameObject.activeSelf || (cameraCulling & (1 << renderer.gameObject.layer)) == 0)
 92                    continue;
 93
 94                // We have to manually render all the submeshes of the selected objects.
 095                for (var i = 0; i < meshCount; i++) { cmd.DrawRenderer(renderer, material, i); }
 96            }
 097        }
 98
 99        private void DrawAvatar((Renderer renderer, int meshCount, float avatarHeight) avatar, int cameraCulling, Comman
 100        {
 0101            if (avatar.renderer == null)
 0102                return;
 103
 104            //Ignore disabled or culled by camera avatars
 0105            if (!avatar.renderer.gameObject.activeSelf || (cameraCulling & (1 << avatar.renderer.gameObject.layer)) == 0
 0106                return;
 107
 0108            for (var i = 0; i < avatar.meshCount; i++)
 109            {
 0110                Material materialToUse = null;
 111
 112                // We use a GPU Skinning based material
 0113                if (avatar.renderer.materials[i] != null)
 114                {
 115                    //Enable it when we are capable of adding the pass into the Toon Shader
 116                    if (USE_BASE_MATERIAL)
 117                    {
 118                        int originalMaterialOutlinerPass = avatar.renderer.materials[i].FindPass("Outliner");
 119
 120                        if (originalMaterialOutlinerPass != -1)
 121                        {
 122                            //The material has a built in pass we can use
 123                            cmd.DrawRenderer(avatar.renderer, avatar.renderer.materials[i], i, originalMaterialOutlinerP
 124                            continue;
 125                        }
 126                    }
 127
 128                    // We use the original material to copy the GPUSkinning values.
 129                    // We cannot use materialToUse.CopyPropertiesFromMaterial because there are non serialized uniforms 
 0130                    materialToUse = new Material(gpuSkinningMaterial);
 0131                    toDispose.Add(materialToUse);
 0132                    CopyAvatarProperties(avatar.renderer.materials[i], materialToUse);
 133                }
 134                else // Fallback to the normal outliner without GPUSkinning
 135                {
 0136                    materialToUse = material;
 137                }
 138
 139                // We have to manually render all the submeshes of the selected objects.
 0140                cmd.DrawRenderer(avatar.renderer, materialToUse, i);
 141            }
 0142        }
 143
 144        private void CopyAvatarProperties(Material source, Material target)
 145        {
 0146            target.SetMatrixArray(BIND_POSES, source.GetMatrixArray(BIND_POSES));
 0147            target.SetMatrix(RENDERER_WORLD_INVERSE, source.GetMatrix(RENDERER_WORLD_INVERSE));
 0148            target.SetMatrixArray(BONE_MATRICES, source.GetMatrixArray(BONE_MATRICES));
 149
 0150            if (source.HasTexture(AVATAR_MAP1))
 0151                target.SetTexture(AVATAR_MAP1, source.GetTexture(AVATAR_MAP1));
 152
 0153            if (source.HasTexture(AVATAR_MAP2))
 0154                target.SetTexture(AVATAR_MAP2, source.GetTexture(AVATAR_MAP2));
 155
 0156            if (source.HasTexture(AVATAR_MAP3))
 0157                target.SetTexture(AVATAR_MAP3, source.GetTexture(AVATAR_MAP3));
 158
 0159            if (source.HasTexture(AVATAR_MAP4))
 0160                target.SetTexture(AVATAR_MAP4, source.GetTexture(AVATAR_MAP4));
 161
 0162            if (source.HasTexture(AVATAR_MAP5))
 0163                target.SetTexture(AVATAR_MAP5, source.GetTexture(AVATAR_MAP5));
 164
 0165            if (source.HasTexture(AVATAR_MAP6))
 0166                target.SetTexture(AVATAR_MAP6, source.GetTexture(AVATAR_MAP6));
 167
 0168            if (source.HasTexture(AVATAR_MAP7))
 0169                target.SetTexture(AVATAR_MAP7, source.GetTexture(AVATAR_MAP7));
 170
 0171            if (source.HasTexture(AVATAR_MAP8))
 0172                target.SetTexture(AVATAR_MAP8, source.GetTexture(AVATAR_MAP8));
 173
 0174            if (source.HasTexture(AVATAR_MAP9))
 0175                target.SetTexture(AVATAR_MAP9, source.GetTexture(AVATAR_MAP9));
 176
 0177            if (source.HasTexture(AVATAR_MAP10))
 0178                target.SetTexture(AVATAR_MAP10, source.GetTexture(AVATAR_MAP10));
 179
 0180            if (source.HasTexture(AVATAR_MAP11))
 0181                target.SetTexture(AVATAR_MAP11, source.GetTexture(AVATAR_MAP11));
 182
 0183            if (source.HasTexture(AVATAR_MAP12))
 0184                target.SetTexture(AVATAR_MAP12, source.GetTexture(AVATAR_MAP12));
 0185        }
 186
 187        public override void FrameCleanup(CommandBuffer cmd)
 188        {
 0189            cmd.ReleaseTemporaryRT(outlineTextureHandle.id);
 190
 0191            for (var index = 0; index < toDispose.Count; index++) { Object.Destroy(toDispose[index]); }
 192
 0193            toDispose.Clear();
 0194        }
 195    }
 196
 197    public OutlineRenderersSO renderers;
 198    private OutlinerRenderPass scriptablePass;
 199
 200    private RenderTargetHandle outlineTexture;
 201
 202    public override void Create()
 203    {
 2204        scriptablePass = new OutlinerRenderPass(renderers)
 205        {
 206            renderPassEvent = RenderPassEvent.AfterRenderingTransparents,
 207        };
 208
 2209        outlineTexture.Init("_OutlineTexture");
 2210    }
 211
 212    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
 213    {
 0214        scriptablePass.Setup(renderingData.cameraData.cameraTargetDescriptor, outlineTexture);
 0215        renderer.EnqueuePass(scriptablePass);
 0216    }
 217}