Files
2024-11-20 15:21:28 +01:00

331 lines
13 KiB
C#

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<StarObject>();
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 <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
// 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 <c>ScriptableRenderContext</c> 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<StarObject>();
moonObject = FindObjectOfType<MoonObject>();
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<ShaderTagId> shaderTagIds = new List<ShaderTagId>()
{
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<MoonObject>();
}
}
}
}
}