using System; using XCEngine; using XCEngine.Rendering; namespace XCEngine.Rendering.Universal { public abstract class ScriptableRenderPass { private const string kColorScaleFullscreenPassName = "Universal.ColorScaleFullscreen"; private const string kShaderVectorFullscreenPassName = "Universal.ShaderVectorFullscreen"; protected ScriptableRenderPass() { } public RenderPassEvent renderPassEvent { get; protected set; } = RenderPassEvent.BeforeRenderingOpaques; public virtual bool SupportsStage( CameraFrameStage stage) { CameraFrameStage resolvedStage; return TryResolveStage( renderPassEvent, out resolvedStage) && resolvedStage == stage; } internal bool Record( ScriptableRenderContext context, RenderingData renderingData) { return RecordRenderGraph( context, renderingData); } protected abstract bool RecordRenderGraph( ScriptableRenderContext context, RenderingData renderingData); protected bool RecordColorScaleFullscreenPass( ScriptableRenderContext context, Vector4 colorScale) { RenderGraphTextureHandle sourceColor; RenderGraphTextureHandle outputColor; return TryResolveDefaultFullscreenTargets( context, out sourceColor, out outputColor) && RecordColorScaleFullscreenPass( context, sourceColor, outputColor, colorScale); } protected bool RecordColorScaleFullscreenPass( ScriptableRenderContext context, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, Vector4 colorScale, string passName = null) { if (context == null || !outputColor.isValid) { return false; } RenderGraphRasterPassBuilder passBuilder = context.AddRasterPass( ResolveFullscreenPassName( passName, kColorScaleFullscreenPassName)); if (sourceColor.isValid) { passBuilder.UseColorSource(sourceColor); } return passBuilder .SetColorAttachment(outputColor) .SetColorScaleFullscreenExecution(colorScale) .Commit(); } protected bool RecordShaderVectorFullscreenPass( ScriptableRenderContext context, string shaderPath, Vector4 vectorPayload, string passName = null) { if (string.IsNullOrEmpty(shaderPath)) { throw new ArgumentException( "Fullscreen shader path cannot be null or empty.", nameof(shaderPath)); } RenderGraphTextureHandle sourceColor; RenderGraphTextureHandle outputColor; return TryResolveDefaultFullscreenTargets( context, out sourceColor, out outputColor) && RecordShaderVectorFullscreenPass( context, sourceColor, outputColor, shaderPath, vectorPayload, passName: passName); } protected bool RecordShaderVectorFullscreenPass( ScriptableRenderContext context, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, string shaderPath, Vector4 vectorPayload, string shaderPassName = null, string passName = null) { if (string.IsNullOrEmpty(shaderPath)) { throw new ArgumentException( "Fullscreen shader path cannot be null or empty.", nameof(shaderPath)); } if (context == null || !outputColor.isValid) { return false; } RenderGraphRasterPassBuilder passBuilder = context.AddRasterPass( ResolveFullscreenPassName( passName, kShaderVectorFullscreenPassName)); if (sourceColor.isValid) { passBuilder.UseColorSource(sourceColor); } return passBuilder .SetColorAttachment(outputColor) .SetShaderVectorFullscreenExecution( shaderPath, vectorPayload, shaderPassName) .Commit(); } internal static bool TryResolveStage( RenderPassEvent passEvent, out CameraFrameStage stage) { switch (passEvent) { case RenderPassEvent.BeforeRenderingOpaques: case RenderPassEvent.RenderOpaques: case RenderPassEvent.AfterRenderingOpaques: case RenderPassEvent.BeforeRenderingSkybox: case RenderPassEvent.RenderSkybox: case RenderPassEvent.AfterRenderingSkybox: case RenderPassEvent.BeforeRenderingTransparents: case RenderPassEvent.RenderTransparents: case RenderPassEvent.AfterRenderingTransparents: stage = CameraFrameStage.MainScene; return true; case RenderPassEvent.BeforeRenderingPostProcessing: case RenderPassEvent.AfterRenderingPostProcessing: stage = CameraFrameStage.PostProcess; return true; case RenderPassEvent.BeforeRenderingFinalOutput: case RenderPassEvent.AfterRenderingFinalOutput: stage = CameraFrameStage.FinalOutput; return true; default: stage = CameraFrameStage.MainScene; return false; } } private static bool TryResolveDefaultFullscreenTargets( ScriptableRenderContext context, out RenderGraphTextureHandle sourceColor, out RenderGraphTextureHandle outputColor) { sourceColor = new RenderGraphTextureHandle(); outputColor = new RenderGraphTextureHandle(); if (context == null) { return false; } sourceColor = context.sourceColorTexture; outputColor = context.primaryColorTarget; return sourceColor.isValid && outputColor.isValid; } private static string ResolveFullscreenPassName( string passName, string defaultPassName) { return string.IsNullOrEmpty(passName) ? defaultPassName : passName; } } }