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

334 lines
11 KiB
C#

using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public sealed class UniversalRenderer : ScriptableRenderer
{
private const string kMainLightShadowsKeyword =
"XC_MAIN_LIGHT_SHADOWS";
private readonly UniversalRendererData m_rendererData;
private readonly BuiltinFinalColorPass m_builtinFinalColorPass =
new BuiltinFinalColorPass();
private readonly DrawObjectsPass m_drawShadowCasterPass =
new DrawObjectsPass(
RenderPassEvent.BeforeRenderingShadows,
SceneRenderPhase.Opaque,
RendererListDesc.CreateDefault(
RendererListType.ShadowCaster));
private readonly DrawObjectsPass m_drawDepthPrepass =
new DrawObjectsPass(
RenderPassEvent.BeforeRenderingPrePasses,
SceneRenderPhase.Opaque,
RendererListDesc.CreateDefault(
RendererListType.Opaque));
private readonly DrawObjectsPass m_drawOpaqueObjectsPass =
new DrawObjectsPass(
RenderPassEvent.RenderOpaques,
SceneRenderPhase.Opaque,
RendererListDesc.CreateDefault(
RendererListType.Opaque));
private readonly DrawSkyboxPass m_drawSkyboxPass =
new DrawSkyboxPass();
private readonly DrawObjectsPass m_drawTransparentObjectsPass =
new DrawObjectsPass(
RenderPassEvent.RenderTransparents,
SceneRenderPhase.Transparent,
RendererListDesc.CreateDefault(
RendererListType.Transparent));
public UniversalRenderer(
UniversalRendererData rendererData)
{
m_rendererData =
rendererData ??
ScriptableObject
.CreateInstance<UniversalRendererData>() ??
new UniversalRendererData();
}
protected override void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null)
{
return;
}
ConfigureShadowCasterStage(
context,
m_rendererData.GetShadowCasterBlockInstance());
ConfigureDepthOnlyStage(
context,
m_rendererData.GetDepthPrepassBlockInstance());
}
protected override void FinalizeCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null)
{
return;
}
base.FinalizeCameraFramePlan(context);
ConfigureFinalOutputStage(context);
}
protected override void ConfigureRenderSceneSetup(
RenderSceneSetupContext context)
{
if (context == null)
{
return;
}
context.SetEnvironmentNone();
context.ClearGlobalShaderKeywords();
Camera camera = context.camera;
if (ShouldUseSkyboxEnvironment(
context,
camera))
{
if (camera.hasSkyboxMaterial)
{
context.UseCameraSkyboxMaterial();
}
else
{
context.SetProceduralSkybox(
camera.skyboxTopColor,
camera.skyboxHorizonColor,
camera.skyboxBottomColor);
}
}
context.SetGlobalShaderKeyword(
kMainLightShadowsKeyword,
context.hasMainDirectionalShadow);
}
protected override void ConfigureDirectionalShadowExecutionState(
DirectionalShadowExecutionContext context)
{
if (context == null)
{
return;
}
ShadowCasterBlockData shadowCaster =
m_rendererData.GetShadowCasterBlockInstance();
if (!context.hasPlannedMainDirectionalShadow ||
shadowCaster == null ||
!shadowCaster.enabled)
{
context.ClearDirectionalShadowExecution();
return;
}
context.UseDefaultMainDirectionalShadowExecution();
}
protected override void AddRenderPasses(
RenderingData renderingData)
{
if (renderingData == null)
{
return;
}
UniversalMainSceneData mainScene =
m_rendererData.GetMainSceneInstance();
ShadowCasterBlockData shadowCaster =
m_rendererData.GetShadowCasterBlockInstance();
DepthPrepassBlockData depthPrepass =
m_rendererData.GetDepthPrepassBlockInstance();
if (shadowCaster.enabled)
{
EnqueueShadowCasterPasses(shadowCaster);
}
if (depthPrepass.enabled)
{
EnqueueDepthPrepass(depthPrepass);
}
if (mainScene.renderOpaque)
{
EnqueueOpaquePasses(mainScene);
}
if (mainScene.renderSkybox)
{
EnqueueSkyboxPasses(mainScene);
}
if (mainScene.renderTransparent)
{
EnqueueTransparentPasses(mainScene);
}
EnqueueFinalOutputPasses(renderingData);
}
private void EnqueueShadowCasterPasses(
ShadowCasterBlockData shadowCaster)
{
m_drawShadowCasterPass.Configure(
shadowCaster.passEvent,
SceneRenderPhase.Opaque,
shadowCaster.rendererListDesc,
shadowCaster.drawingSettings);
EnqueuePass(m_drawShadowCasterPass);
}
private void EnqueueDepthPrepass(
DepthPrepassBlockData depthPrepass)
{
m_drawDepthPrepass.Configure(
depthPrepass.passEvent,
SceneRenderPhase.Opaque,
depthPrepass.rendererListDesc,
depthPrepass.drawingSettings);
EnqueuePass(m_drawDepthPrepass);
}
private void EnqueueOpaquePasses(
UniversalMainSceneData mainScene)
{
m_drawOpaqueObjectsPass.Configure(
mainScene.opaquePassEvent,
SceneRenderPhase.Opaque,
mainScene.opaqueRendererListDesc,
mainScene.opaqueDrawingSettings);
EnqueuePass(m_drawOpaqueObjectsPass);
}
private void EnqueueSkyboxPasses(
UniversalMainSceneData mainScene)
{
m_drawSkyboxPass.Configure(
mainScene.skyboxPassEvent);
EnqueuePass(m_drawSkyboxPass);
}
private void EnqueueTransparentPasses(
UniversalMainSceneData mainScene)
{
m_drawTransparentObjectsPass.Configure(
mainScene.transparentPassEvent,
SceneRenderPhase.Transparent,
mainScene.transparentRendererListDesc,
mainScene.transparentDrawingSettings);
EnqueuePass(m_drawTransparentObjectsPass);
}
private static void ConfigureShadowCasterStage(
ScriptableRenderPipelinePlanningContext context,
ShadowCasterBlockData shadowCaster)
{
if (shadowCaster != null &&
shadowCaster.enabled)
{
context.RequestShadowCasterStage();
return;
}
context.ClearShadowCasterStage();
}
private static void ConfigureDepthOnlyStage(
ScriptableRenderPipelinePlanningContext context,
DepthPrepassBlockData depthPrepass)
{
if (depthPrepass != null &&
depthPrepass.enabled &&
context.RequestCameraDepthOnlyStage())
{
return;
}
context.ClearDepthOnlyStage();
}
private static void ConfigureFinalOutputStage(
ScriptableRenderPipelinePlanningContext context)
{
if (!context.HasFinalColorProcessing())
{
return;
}
context.ClearFullscreenStage(
CameraFrameStage.FinalOutput);
CameraFrameColorSource finalOutputSource =
CameraFrameColorSource.MainSceneColor;
if (context.IsStageRequested(
CameraFrameStage.PostProcess))
{
CameraFrameColorSource postProcessSource =
context.GetStageColorSource(
CameraFrameStage.PostProcess);
if (postProcessSource !=
CameraFrameColorSource.ExplicitSurface)
{
if (!context.UsesGraphManagedOutputColor(
CameraFrameStage.PostProcess))
{
context.ClearFullscreenStage(
CameraFrameStage.PostProcess);
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
postProcessSource,
true);
}
finalOutputSource =
CameraFrameColorSource.PostProcessColor;
}
}
context.RequestFullscreenStage(
CameraFrameStage.FinalOutput,
finalOutputSource);
}
private static bool ShouldUseSkyboxEnvironment(
RenderSceneSetupContext context,
Camera camera)
{
if (context == null ||
camera == null ||
!context.hasMainSceneDepthAttachment ||
(context.clearFlags & RenderClearFlags.Color) == 0 ||
!camera.skyboxEnabled)
{
return false;
}
return camera.projectionType ==
CameraProjectionType.Perspective;
}
private void EnqueueFinalOutputPasses(
RenderingData renderingData)
{
if (renderingData == null)
{
return;
}
if (!renderingData.isFinalOutputStage &&
!renderingData.finalColorData.requiresProcessing)
{
return;
}
EnqueuePass(m_builtinFinalColorPass);
}
}
}