using Golems.RenderFeatures; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace Golems { public class ComposeOutlineScriptableRenderFeature : SourceToDestinationBlitRenderFeature { [SerializeField] private bool m_IsEnabled = true; [Header("Compose things")] [SerializeField] private Material m_CompositeMaterial = default; private ComposeOutlinePass m_Pass; public override void Create() { m_Pass = new ComposeOutlinePass(m_CompositeMaterial); DoCreate(); } private void DebugSetEnabledState(bool state) { m_IsEnabled = state; } private bool DebugGetEnabledState() { return m_IsEnabled; } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (IsSourceAndDestinationSame()) { // // The source and destination are same can skip the pass if there is // nothing to render. // var outlineObjects = OutlineCollection.RendererBundles; if (outlineObjects == null || outlineObjects.Count <= 0) { return; } } m_Pass.Setup(m_IsEnabled,m_WhenToInsert, renderer.cameraColorTarget, m_SourceTextureSourceType, m_SourceNamedTemporaryNameHash, m_DestinationTextureSourceType, m_DestinationNamedTemporaryNameHash, m_TempCopyNamedTemporaryNameHash); renderer.EnqueuePass(m_Pass); } } public class ComposeOutlinePass : SourceToDestinationBlitRenderPass { private const string k_ProfilerIdent = "ComposeOutlinePass"; private Material m_CompositeMat = null; private bool m_IsEnabled; private readonly int m_BlurTexId = Shader.PropertyToID("_BlurTex"); private readonly int m_DefaultDrawObjectsTexId = Shader.PropertyToID("_DefaultDrawObjects"); public ComposeOutlinePass(Material compositeMaterial) { m_CompositeMat = compositeMaterial; } public void Setup(bool isEnabled, RenderPassEvent whenToRender, RenderTargetIdentifier cameraColourTargetIdentifier, RenderFeatures.TextureSourceType sourceSourceType, int tempSourceTextureHash, RenderFeatures.TextureSourceType destinationSourceType, int tempDestinationTextureHash, int sameSourceDestTextureHash) { m_IsEnabled = isEnabled; DoSetup(whenToRender, cameraColourTargetIdentifier, sourceSourceType, tempSourceTextureHash, destinationSourceType, tempDestinationTextureHash, sameSourceDestTextureHash); } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { DoOnCameraSetup(cmd, ref renderingData); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { // // The OutlineCollection.NumberOfObjectsRendered is set during the // OutlineScriptableRenderPass.Execute() so if that did not render anything then there is // nothing to compose. // if (!m_GoodToExecute) { return; } bool doCopyOnly = (OutlineCollection.NumberOfObjectsRendered <= 0) || !m_IsEnabled; if (doCopyOnly) { if (!m_SourceAndDestinationSame) { // // Copy the source to the destination // var copyCmd = CommandBufferPool.Get(k_ProfilerIdent); copyCmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier); context.ExecuteCommandBuffer(copyCmd); CommandBufferPool.Release(copyCmd); } return; } var cmd = CommandBufferPool.Get(k_ProfilerIdent); cmd.SetGlobalTexture("_BlurTex", m_BlurTexId); cmd.SetGlobalTexture("_DefaultDrawObjects", m_DefaultDrawObjectsTexId); if (m_SourceAndDestinationSame) { cmd.Blit(m_SourceTargetIdentifier, m_TempCopyTargetIdentifier, m_CompositeMat); cmd.Blit(m_TempCopyTargetIdentifier, m_DestinationTargetIdentifier); } else { cmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier, m_CompositeMat); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } } }