using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace OccaSoftware.Altos { public class StarsRenderFeature : ScriptableRendererFeature { class StarRenderPass : ScriptableRenderPass { private RenderTargetHandle starsRT; private const string featureDescription = "RenderStarsOS"; private const string starInputTexID = "_Celestial_Stars_Input"; private const string starRenderTargetName = "RenderStars"; GameObject starGameObject = null; public void GetStarObject() { if (starGameObject == null) { StarObject temp = FindObjectOfType(); if (temp != null) starGameObject = temp.gameObject; } } public StarRenderPass() { starsRT.Init(starRenderTargetName); } // This method is called before executing the render pass. // It can be used to configure render targets and their clear state. Also to create temporary render target textures. // When empty this render pass will render to the active camera render target. // You should never call CommandBuffer.SetRenderTarget. Instead call ConfigureTarget and ConfigureClear. // The render pipeline will ensure target setup and clearing happens in an performance manner. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { RenderTextureDescriptor rtDescriptor = cameraTextureDescriptor; rtDescriptor.colorFormat = RenderTextureFormat.DefaultHDR; cmd.GetTemporaryRT(starsRT.id, rtDescriptor); ConfigureTarget(starsRT.id); ConfigureClear(ClearFlag.All, Color.black); GetStarObject(); } // Here you can implement the rendering logic. // Use ScriptableRenderContext to issue drawing commands or execute command buffers // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { if (starGameObject == null) return; #region Define Drawing and Filtering Settings DrawingSettings drawingSettings = CreateDrawingSettings(RenderPassHelpers.shaderTagIds, ref renderingData, SortingCriteria.None); FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.transparent, RenderPassHelpers.FindMaskInt(starGameObject)); #endregion CommandBuffer cmd = CommandBufferPool.Get(featureDescription); #region Write Stars to Star Render Texture context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings); cmd.SetGlobalTexture(starInputTexID, starsRT.Identifier()); #endregion context.ExecuteCommandBuffer(cmd); cmd.Clear(); CommandBufferPool.Release(cmd); } } class MoonRenderPass : ScriptableRenderPass { RenderTargetHandle moonRT; MoonObject moonObject = null; private const string moonRTHandleName = "Moon RT"; private const string moonRenderID = "_Celestial_Moon_Input"; private const string featureDescription = "Render Moon OS"; private const RenderTextureFormat targetFormat = RenderTextureFormat.DefaultHDR; public MoonRenderPass() { moonRT.Init(moonRTHandleName); RenderPassHelpers.GetMoonObject(ref moonObject); } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { RenderPassHelpers.Configure(ref cmd, cameraTextureDescriptor, targetFormat, moonRT, this, moonObject); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { RenderPassHelpers.Execute(moonObject, featureDescription, moonRenderID, true, moonRT, ref context, ref renderingData, this); } public override void FrameCleanup(CommandBuffer cmd) { cmd.ReleaseTemporaryRT(moonRT.id); } } class MaskRenderPass : ScriptableRenderPass { RenderTargetHandle maskRT; MoonObject moonObject = null; private const string maskRTHandleName = "Mask RT"; private const string moonMaskTexID = "_Celestial_Merge_Mask"; private const string featureDescription = "Render Mask OS"; private const RenderTextureFormat targetFormat = RenderTextureFormat.R8; public MaskRenderPass() { maskRT.Init(maskRTHandleName); RenderPassHelpers.GetMoonObject(ref moonObject); } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { RenderPassHelpers.Configure(ref cmd, cameraTextureDescriptor, targetFormat, maskRT, this, moonObject); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { RenderPassHelpers.Execute(moonObject, featureDescription, moonMaskTexID, false, maskRT, ref context, ref renderingData, this); } public override void FrameCleanup(CommandBuffer cmd) { cmd.ReleaseTemporaryRT(maskRT.id); } } class MergeCelestialRenderPass : ScriptableRenderPass { private const string featureDescription = "Merge Celestial OS"; private const string mergeRenderTargetName = "CelestialMergeTargetOS"; private const string mergeShaderPath = "Shader Graphs/Celestial Merge Pass_OS"; private Material starMergeMaterial = null; private RenderTargetHandle starMergeTarget; public MergeCelestialRenderPass() { starMergeTarget.Init(mergeRenderTargetName); if (starMergeMaterial == null) starMergeMaterial = CoreUtils.CreateEngineMaterial(mergeShaderPath); } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { RenderTextureDescriptor descriptor = cameraTextureDescriptor; descriptor.colorFormat = RenderTextureFormat.DefaultHDR; cmd.GetTemporaryRT(starMergeTarget.id, descriptor); ConfigureTarget(starMergeTarget.id); ConfigureClear(ClearFlag.Color, Color.black); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { CommandBuffer cmd = CommandBufferPool.Get(featureDescription); RenderPassHelpers.SetFadeFalloff(starMergeMaterial, 0.2f); RenderTargetIdentifier source = renderingData.cameraData.renderer.cameraColorTarget; #region Merge Stars to Screen Blit(cmd, source, starMergeTarget.Identifier(), starMergeMaterial); Blit(cmd, starMergeTarget.Identifier(), source); #endregion context.ExecuteCommandBuffer(cmd); cmd.Clear(); CommandBufferPool.Release(cmd); } public override void FrameCleanup(CommandBuffer cmd) { cmd.ReleaseTemporaryRT(starMergeTarget.id); } } StarRenderPass starRenderPass; MoonRenderPass moonRenderPass; MaskRenderPass maskRenderPass; MergeCelestialRenderPass mergeCelestialRenderPass; StarObject starObject; MoonObject moonObject; private void OnEnable() { Helpers.RenderFeatureOnEnable(Recreate); } private void OnDisable() { Helpers.RenderFeatureOnDisable(Recreate); } private void Recreate(UnityEngine.SceneManagement.Scene current, UnityEngine.SceneManagement.Scene next) { Create(); } public override void Create() { starObject = FindObjectOfType(); moonObject = FindObjectOfType(); if(starObject != null && moonObject != null) { starRenderPass = new StarRenderPass(); moonRenderPass = new MoonRenderPass(); maskRenderPass = new MaskRenderPass(); mergeCelestialRenderPass = new MergeCelestialRenderPass(); // Configures where the render pass should be injected. starRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingSkybox + 1; moonRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingSkybox + 2; maskRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingSkybox + 3; mergeCelestialRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingSkybox + 4; } } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if(starObject != null && moonObject != null) { Camera camera = renderingData.cameraData.camera; if (camera.name == "Preview Camera" || camera.name == "Preview Scene Camera") return; if (camera.cameraType == CameraType.Reflection) return; renderer.EnqueuePass(starRenderPass); renderer.EnqueuePass(moonRenderPass); renderer.EnqueuePass(maskRenderPass); renderer.EnqueuePass(mergeCelestialRenderPass); } } private static class RenderPassHelpers { public static List shaderTagIds = new List() { new ShaderTagId("UniversalForward"), new ShaderTagId("SRPDefaultUnlit"), new ShaderTagId("UniversalForwardOnly") }; public static int FindMaskInt(GameObject gameObject) { return LayerMask.GetMask(LayerMask.LayerToName(gameObject.layer)); } public static class ShaderParam { public static int overrideMaskEnabled = Shader.PropertyToID("_OVERRIDE_MATERIAL_MOON_ENABLED"); public static int fadeFalloff = Shader.PropertyToID("_Celestial_Merge_Fade_Falloff"); } public static void SetFadeFalloff(Material mat, float val) { mat.SetFloat(ShaderParam.fadeFalloff, val); } public static void Configure(ref CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor, RenderTextureFormat targetFormat, RenderTargetHandle rtHandle, ScriptableRenderPass pass, MoonObject moonObject) { RenderTextureDescriptor rtDescriptor = cameraTextureDescriptor; rtDescriptor.colorFormat = targetFormat; cmd.GetTemporaryRT(rtHandle.id, rtDescriptor); pass.ConfigureTarget(rtHandle.id); pass.ConfigureClear(ClearFlag.Color, Color.black); } public static void Execute(MoonObject moonObject, string desc, string targetTex, bool overrideMask, RenderTargetHandle rtHandle, ref ScriptableRenderContext context, ref RenderingData renderingData, ScriptableRenderPass pass) { if (moonObject == null) return; CommandBuffer cmd = CommandBufferPool.Get(desc); #region Define Drawing and Filtering Settings DrawingSettings drawingSettings = pass.CreateDrawingSettings(shaderTagIds, ref renderingData, SortingCriteria.None); FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.all, FindMaskInt(moonObject.gameObject)); #endregion #region Write Moon to Moon RT cmd.SetGlobalInt(ShaderParam.overrideMaskEnabled, overrideMask ? 1 : 0); context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings); cmd.SetGlobalTexture(targetTex, rtHandle.Identifier()); #endregion context.ExecuteCommandBuffer(cmd); cmd.Clear(); CommandBufferPool.Release(cmd); } public static void GetMoonObject(ref MoonObject moonObject) { if (moonObject == null) { moonObject = FindObjectOfType(); } } } } }