2026-04-19 02:38:48 +08:00
|
|
|
using System;
|
|
|
|
|
using XCEngine;
|
|
|
|
|
using XCEngine.Rendering;
|
2026-04-19 00:05:29 +08:00
|
|
|
|
2026-04-19 14:04:19 +08:00
|
|
|
namespace XCEngine.Rendering.Universal
|
2026-04-19 02:38:48 +08:00
|
|
|
{
|
2026-04-19 16:17:38 +08:00
|
|
|
internal enum UniversalSceneRecordingKind
|
|
|
|
|
{
|
|
|
|
|
BeforeOpaqueInjection,
|
|
|
|
|
OpaqueScene,
|
|
|
|
|
AfterOpaqueInjection,
|
|
|
|
|
BeforeSkyboxInjection,
|
|
|
|
|
SkyboxScene,
|
|
|
|
|
AfterSkyboxInjection,
|
|
|
|
|
BeforeTransparentInjection,
|
|
|
|
|
TransparentScene,
|
|
|
|
|
AfterTransparentInjection
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-19 14:04:19 +08:00
|
|
|
internal sealed class UniversalSceneRecordingPass : ScriptableRenderPass
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
2026-04-19 16:17:38 +08:00
|
|
|
private readonly UniversalSceneRecordingKind m_recordingKind;
|
2026-04-19 00:05:29 +08:00
|
|
|
|
2026-04-19 14:04:19 +08:00
|
|
|
public UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent passEvent,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind recordingKind)
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
|
|
|
|
renderPassEvent = passEvent;
|
2026-04-19 16:17:38 +08:00
|
|
|
m_recordingKind = recordingKind;
|
2026-04-19 00:05:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override bool RecordRenderGraph(
|
2026-04-19 13:05:57 +08:00
|
|
|
ScriptableRenderContext context,
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderingData renderingData)
|
|
|
|
|
{
|
|
|
|
|
return context != null &&
|
|
|
|
|
renderingData != null &&
|
|
|
|
|
renderingData.isMainSceneStage &&
|
2026-04-19 16:17:38 +08:00
|
|
|
RecordSceneStep(context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool RecordSceneStep(
|
|
|
|
|
ScriptableRenderContext context)
|
|
|
|
|
{
|
|
|
|
|
switch (m_recordingKind)
|
|
|
|
|
{
|
|
|
|
|
case UniversalSceneRecordingKind.BeforeOpaqueInjection:
|
|
|
|
|
return RecordBeforeOpaqueInjection(context);
|
|
|
|
|
case UniversalSceneRecordingKind.OpaqueScene:
|
|
|
|
|
return RecordOpaqueScenePhase(context);
|
|
|
|
|
case UniversalSceneRecordingKind.AfterOpaqueInjection:
|
|
|
|
|
return RecordAfterOpaqueInjection(context);
|
|
|
|
|
case UniversalSceneRecordingKind.BeforeSkyboxInjection:
|
|
|
|
|
return RecordBeforeSkyboxInjection(context);
|
|
|
|
|
case UniversalSceneRecordingKind.SkyboxScene:
|
|
|
|
|
return RecordSkyboxScenePhase(context);
|
|
|
|
|
case UniversalSceneRecordingKind.AfterSkyboxInjection:
|
|
|
|
|
return RecordAfterSkyboxInjection(context);
|
|
|
|
|
case UniversalSceneRecordingKind.BeforeTransparentInjection:
|
|
|
|
|
return RecordBeforeTransparentInjection(context);
|
|
|
|
|
case UniversalSceneRecordingKind.TransparentScene:
|
|
|
|
|
return RecordTransparentScenePhase(context);
|
|
|
|
|
case UniversalSceneRecordingKind.AfterTransparentInjection:
|
|
|
|
|
return RecordAfterTransparentInjection(context);
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-04-19 00:05:29 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-19 14:04:19 +08:00
|
|
|
internal sealed class UniversalSceneFeature : ScriptableRendererFeature
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalRendererData m_rendererData;
|
|
|
|
|
private readonly UniversalSceneRecordingPass m_beforeOpaquePass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.BeforeRenderingOpaques,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.BeforeOpaqueInjection);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_opaquePass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.RenderOpaques,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.OpaqueScene);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_afterOpaquePass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.AfterRenderingOpaques,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.AfterOpaqueInjection);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_beforeSkyboxPass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.BeforeRenderingSkybox,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.BeforeSkyboxInjection);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_skyboxPass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.RenderSkybox,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.SkyboxScene);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_afterSkyboxPass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.AfterRenderingSkybox,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.AfterSkyboxInjection);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_beforeTransparentPass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.BeforeRenderingTransparents,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.BeforeTransparentInjection);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_transparentPass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.RenderTransparents,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.TransparentScene);
|
2026-04-19 14:04:19 +08:00
|
|
|
private readonly UniversalSceneRecordingPass m_afterTransparentPass =
|
|
|
|
|
new UniversalSceneRecordingPass(
|
2026-04-19 00:05:29 +08:00
|
|
|
RenderPassEvent.AfterRenderingTransparents,
|
2026-04-19 16:17:38 +08:00
|
|
|
UniversalSceneRecordingKind.AfterTransparentInjection);
|
2026-04-19 00:05:29 +08:00
|
|
|
|
2026-04-19 14:04:19 +08:00
|
|
|
public UniversalSceneFeature(
|
|
|
|
|
UniversalRendererData rendererData)
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
|
|
|
|
m_rendererData = rendererData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void AddRenderPasses(
|
|
|
|
|
ScriptableRenderer renderer,
|
|
|
|
|
RenderingData renderingData)
|
|
|
|
|
{
|
|
|
|
|
if (renderer == null ||
|
|
|
|
|
renderingData == null ||
|
|
|
|
|
!renderingData.isMainSceneStage ||
|
|
|
|
|
m_rendererData == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_rendererData.renderOpaque)
|
|
|
|
|
{
|
|
|
|
|
renderer.EnqueuePass(m_beforeOpaquePass);
|
|
|
|
|
renderer.EnqueuePass(m_opaquePass);
|
|
|
|
|
renderer.EnqueuePass(m_afterOpaquePass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_rendererData.renderSkybox)
|
|
|
|
|
{
|
|
|
|
|
renderer.EnqueuePass(m_beforeSkyboxPass);
|
|
|
|
|
renderer.EnqueuePass(m_skyboxPass);
|
|
|
|
|
renderer.EnqueuePass(m_afterSkyboxPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_rendererData.renderTransparent)
|
|
|
|
|
{
|
|
|
|
|
renderer.EnqueuePass(m_beforeTransparentPass);
|
|
|
|
|
renderer.EnqueuePass(m_transparentPass);
|
|
|
|
|
renderer.EnqueuePass(m_afterTransparentPass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-19 14:04:19 +08:00
|
|
|
public sealed class UniversalRenderer : ScriptableRenderer
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
2026-04-19 14:04:19 +08:00
|
|
|
public UniversalRenderer(
|
|
|
|
|
UniversalRendererData rendererData)
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
2026-04-19 14:04:19 +08:00
|
|
|
UniversalRendererData resolvedData =
|
|
|
|
|
rendererData ?? new UniversalRendererData();
|
|
|
|
|
AddFeature(new UniversalSceneFeature(resolvedData));
|
2026-04-19 00:05:29 +08:00
|
|
|
|
|
|
|
|
ScriptableRendererFeature[] rendererFeatures =
|
|
|
|
|
resolvedData.CreateRendererFeaturesInstance();
|
|
|
|
|
for (int i = 0; i < rendererFeatures.Length; ++i)
|
|
|
|
|
{
|
|
|
|
|
AddFeature(rendererFeatures[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-19 02:38:48 +08:00
|
|
|
|