Files
XCEngine/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs

339 lines
11 KiB
C#
Raw Normal View History

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";
private enum RecordedScenePhase
{
Opaque = 0,
Skybox = 1,
Transparent = 3
}
private enum RecordedSceneInjectionPoint
{
BeforeOpaque = 0,
AfterOpaque = 1,
BeforeSkybox = 2,
AfterSkybox = 3,
BeforeTransparent = 4,
AfterTransparent = 5
}
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 RecordScene(
ScriptableRenderContext context)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordScene(
context.nativeHandle);
}
protected bool RecordOpaqueScenePhase(
ScriptableRenderContext context)
{
return RecordScenePhaseInternal(
context,
RecordedScenePhase.Opaque);
}
protected bool RecordSkyboxScenePhase(
ScriptableRenderContext context)
{
return RecordScenePhaseInternal(
context,
RecordedScenePhase.Skybox);
}
protected bool RecordTransparentScenePhase(
ScriptableRenderContext context)
{
return RecordScenePhaseInternal(
context,
RecordedScenePhase.Transparent);
}
protected bool RecordBeforeOpaqueInjection(
ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.BeforeOpaque);
}
protected bool RecordAfterOpaqueInjection(
ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.AfterOpaque);
}
protected bool RecordBeforeSkyboxInjection(
ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.BeforeSkybox);
}
protected bool RecordAfterSkyboxInjection(
ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.AfterSkybox);
}
protected bool RecordBeforeTransparentInjection(
ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.BeforeTransparent);
}
protected bool RecordAfterTransparentInjection(
ScriptableRenderContext context)
{
return RecordSceneInjectionPointInternal(
context,
RecordedSceneInjectionPoint.AfterTransparent);
}
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 bool RecordScenePhaseInternal(
ScriptableRenderContext context,
RecordedScenePhase scenePhase)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordScenePhase(
context.nativeHandle,
(int)scenePhase);
}
private bool RecordSceneInjectionPointInternal(
ScriptableRenderContext context,
RecordedSceneInjectionPoint injectionPoint)
{
return context != null &&
InternalCalls
.Rendering_ScriptableRenderContext_RecordSceneInjectionPoint(
context.nativeHandle,
(int)injectionPoint);
}
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;
}
}
}