refactor(srp): move core stage defaults into universal renderer
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# SRP Unity-Style URP Core Renderer Ownership Plan
|
||||
|
||||
日期:2026-04-21
|
||||
|
||||
## 阶段目标
|
||||
|
||||
在已经完成 `ShadowCaster` stage ownership 的基础上,继续把 URP 的核心职责收回到 `UniversalRenderer` 本体,向 Unity 的 `ScriptableRenderer` 组织方式靠拢。
|
||||
|
||||
这一阶段先不碰 deferred,也不碰大范围的 RenderPassEvent 扩表。先把最明显、最不符合 Unity 的地方收干净:
|
||||
|
||||
- `FinalColor / FinalOutput` 不再由默认 `RendererFeature` 伪装承载
|
||||
- `UniversalRenderer` 显式拥有核心收尾 stage 的默认规划与录制
|
||||
- `RendererFeature` 只保留扩展/注入职责,不再混入明显属于 renderer core 的默认 pass
|
||||
|
||||
## 当前问题
|
||||
|
||||
当前 managed 层虽然已经有了 `RendererData -> Renderer -> RendererFeature -> Pass` 结构,但还存在一个关键偏差:
|
||||
|
||||
1. `BuiltinFinalColorRendererFeature` 仍然承担 `FinalOutput` stage 的默认规划
|
||||
2. `BuiltinFinalColorRendererFeature` 仍然承担核心 final color pass 的录制
|
||||
3. `UniversalRendererData.rendererFeatures` 默认列表里混入了 renderer core pass
|
||||
|
||||
这跟 Unity 的真实边界不一致。Unity 里:
|
||||
|
||||
- `ScriptableRenderer` 负责核心 pass 的组织
|
||||
- `ScriptableRendererFeature` 负责附加、覆写、注入
|
||||
- `RendererData` 主要是 renderer 配置资产,而不是“默认核心 pass 容器”
|
||||
|
||||
如果继续把 core pass 塞在默认 feature 里,后面会直接影响:
|
||||
|
||||
- renderer 自己的阶段所有权
|
||||
- future renderer variant(不同 renderer)的拆分
|
||||
- 后续 post-process block / shadow block / prepass block 的继续归位
|
||||
|
||||
## 本阶段实施内容
|
||||
|
||||
### 1. 收回 FinalColor 核心职责
|
||||
|
||||
把 `BuiltinFinalColor` 的默认规划与录制从默认 `RendererFeature` 收回到 `UniversalRenderer`:
|
||||
|
||||
1. `UniversalRenderer.ConfigureCameraFramePlan(...)` 显式拥有 `FinalOutput` 的默认规划
|
||||
2. `UniversalRenderer.AddRenderPasses(...)` 显式拥有内建 final color pass 的入队
|
||||
3. 后续 feature 仍然可以在 renderer 之后覆写/补充
|
||||
|
||||
### 2. 清理默认 RendererFeature 列表
|
||||
|
||||
调整 `UniversalRendererData` 的默认 feature 列表,只保留扩展性质的 feature:
|
||||
|
||||
1. `BuiltinFinalColorRendererFeature` 退出默认列表
|
||||
2. `rendererFeatures` 不再承担 renderer core 职责
|
||||
3. 默认 feature 列表表达“扩展点”,而不是“核心管线本体”
|
||||
|
||||
### 3. 保持现有行为不回退
|
||||
|
||||
这一步不是改效果,而是改职责边界:
|
||||
|
||||
1. 有 final color processing 时,`FinalOutput` 仍会被正确请求
|
||||
2. 若 `PostProcess` 已占用 graph-managed color,`FinalOutput` 仍沿用正确 source
|
||||
3. 旧版 `XCEditor` 冒烟结果不能回退
|
||||
|
||||
## 本阶段不做的事情
|
||||
|
||||
1. 不做 deferred renderer
|
||||
2. 不做 GBuffer
|
||||
3. 不做完整 post-process block 体系
|
||||
4. 不做阴影 pass managed 化
|
||||
5. 不一口气重写所有 `RendererFeature`
|
||||
|
||||
## 完成标准
|
||||
|
||||
1. `FinalOutput` 的默认规划位于 `UniversalRenderer`
|
||||
2. 内建 final color pass 的默认录制位于 `UniversalRenderer`
|
||||
3. `UniversalRendererData` 默认 feature 列表不再包含 core final color feature
|
||||
4. 旧版 `XCEditor` Debug 编译通过
|
||||
5. 旧版编辑器冒烟 10 秒以上,并在新的 `editor.log` 中出现 `SceneReady`
|
||||
|
||||
## 下一阶段前置条件
|
||||
|
||||
只有这一阶段收口后,再进入下一个更像 Unity 的阶段:
|
||||
|
||||
- `PostProcess / Core Block Ownership`
|
||||
|
||||
也就是继续把 renderer core 的 block 组织,从 feature 侧收回到 `UniversalRenderer`,为后续更完整的 Unity 风格 `RenderPassEvent` 与 renderer variant 演进做准备。
|
||||
@@ -0,0 +1,99 @@
|
||||
# SRP Unity-Style URP Shadow Stage Ownership Plan
|
||||
|
||||
日期:2026-04-21
|
||||
|
||||
## 阶段目标
|
||||
|
||||
本阶段不做 deferred。本阶段只做一件更关键的事:
|
||||
|
||||
- 按 Unity 的 `SRP -> URP Asset -> RendererData -> Renderer -> RendererFeature/Pass` 分层,
|
||||
把 `ShadowCaster` 阶段的组织权从 native 默认宿主继续收回到 URP 包层。
|
||||
|
||||
当前主线已经完成了 SRP generic seam 收口,但 `ShadowCaster` 仍主要由 native 默认流程决定:
|
||||
|
||||
1. native request/build-plan 默认逻辑决定阴影阶段是否存在。
|
||||
2. URP 目前只能改阴影 planning settings 和 execution policy key,不能显式组织阴影阶段。
|
||||
3. 这会直接阻塞后续 renderer model 和 deferred 演进。
|
||||
|
||||
## 为什么这一阶段优先级最高
|
||||
|
||||
如果现在直接做 deferred,会把以下职责继续错误地压在 C++ 宿主层:
|
||||
|
||||
1. 阶段存在性判定
|
||||
2. ShadowCaster 与 MainScene 的耦合关系
|
||||
3. Forward/Deferred 的 renderer path 组织
|
||||
|
||||
最终会得到一个“有 C# 外壳的 C++ 内建管线”,而不是 Unity 风格的 `SRP + URP`。
|
||||
|
||||
## 对齐 Unity 的实现原则
|
||||
|
||||
这一阶段严格按下面的边界推进:
|
||||
|
||||
1. `ScriptableRenderPipelineAsset`
|
||||
- 只保留 SRP 抽象宿主职责。
|
||||
|
||||
2. `UniversalRenderPipelineAsset`
|
||||
- 负责首方 URP 级别的全局设置与默认 renderer 组织。
|
||||
|
||||
3. `UniversalRendererData`
|
||||
- 负责 renderer 级配置,不再只做 key 映射容器。
|
||||
|
||||
4. `UniversalRenderer`
|
||||
- 负责主场景与阴影等核心 renderer stage 的组织。
|
||||
|
||||
5. `ScriptableRendererFeature`
|
||||
- 负责注入和覆写,不负责继续依赖 native 默认猜测阶段。
|
||||
|
||||
## 本阶段具体工作
|
||||
|
||||
### 1. ShadowCaster 显式规划 API
|
||||
|
||||
给 managed planning context 增加 `ShadowCaster` 显式请求/清理能力:
|
||||
|
||||
1. native `CameraFramePlan` 记录 `ShadowCaster` 显式配置状态。
|
||||
2. managed `ScriptableRenderPipelinePlanningContext` 暴露对应 API。
|
||||
3. `DirectionalShadowRuntime` 尊重显式关闭,不再无条件按 native 默认继续推导。
|
||||
|
||||
### 2. URP 默认阴影阶段归位
|
||||
|
||||
让 `UniversalRenderPipelineAsset` 在 planning 阶段显式声明:
|
||||
|
||||
1. 允许阴影时,请求 `ShadowCaster`
|
||||
2. 关闭阴影时,清理 `ShadowCaster`
|
||||
|
||||
这一步的意义不是改变最终效果,而是把“阶段组织权”显式放回 URP。
|
||||
|
||||
### 3. Feature 覆写路径归位
|
||||
|
||||
让类似 `DisableDirectionalShadowRendererFeature` 这类 feature:
|
||||
|
||||
1. 不再只靠 request 阶段清掉 directional shadow 数据
|
||||
2. 同时在 plan 阶段显式清掉 `ShadowCaster`
|
||||
|
||||
这样以后 renderer feature 覆写路径才符合 Unity 的思路。
|
||||
|
||||
## 本阶段不做的事
|
||||
|
||||
1. 不做 deferred renderer
|
||||
2. 不做 GBuffer
|
||||
3. 不重写整个 shadow runtime
|
||||
4. 不一次性泛化所有 standalone stage
|
||||
|
||||
## 完成标准
|
||||
|
||||
1. managed planning context 可以显式控制 `ShadowCaster`
|
||||
2. `UniversalRenderPipelineAsset` 显式拥有默认阴影阶段组织权
|
||||
3. feature 可以显式覆写 `ShadowCaster`
|
||||
4. 旧版 `XCEditor` Debug 编译通过
|
||||
5. 旧版编辑器冒烟 10 秒以上并出现新的 `SceneReady`
|
||||
|
||||
## 下一阶段前置条件
|
||||
|
||||
只有本阶段完成,才进入下一阶段:
|
||||
|
||||
- `URP Renderer Model Formalization`
|
||||
|
||||
也就是:
|
||||
|
||||
1. 把 `UniversalRendererData` 从“forward 默认配置袋”演进成真正的 renderer data 模型
|
||||
2. 为未来 `ForwardRenderer / DeferredRenderer` 拆分做好结构准备
|
||||
@@ -16,6 +16,11 @@ struct CameraFrameFullscreenStagePlan {
|
||||
CameraFrameColorSource source = CameraFrameColorSource::ExplicitSurface;
|
||||
};
|
||||
|
||||
struct CameraFrameStandaloneStagePlan {
|
||||
bool requested = false;
|
||||
bool explicitlyConfigured = false;
|
||||
};
|
||||
|
||||
struct CameraFrameColorChainPlan {
|
||||
bool usesGraphManagedSceneColor = false;
|
||||
CameraFrameFullscreenStagePlan postProcess = {};
|
||||
@@ -35,6 +40,7 @@ struct CameraFramePlan {
|
||||
RenderPassSequence* preScenePasses = nullptr;
|
||||
RenderPassSequence* postScenePasses = nullptr;
|
||||
RenderPassSequence* overlayPasses = nullptr;
|
||||
CameraFrameStandaloneStagePlan shadowCasterStage = {};
|
||||
CameraFrameColorChainPlan colorChain = {};
|
||||
RenderSurface graphManagedSceneSurface = {};
|
||||
|
||||
@@ -64,8 +70,14 @@ struct CameraFramePlan {
|
||||
void ClearFullscreenStage(
|
||||
CameraFrameStage stage,
|
||||
bool explicitlyConfigured = false);
|
||||
bool RequestShadowCasterStage(
|
||||
bool explicitlyConfigured = false);
|
||||
void ClearShadowCasterStage(
|
||||
bool explicitlyConfigured = false);
|
||||
bool HasExplicitFullscreenStageConfiguration(
|
||||
CameraFrameStage stage) const;
|
||||
bool HasExplicitShadowCasterStageConfiguration() const;
|
||||
bool IsShadowCasterStageRequested() const;
|
||||
bool IsPostProcessStageValid() const;
|
||||
bool IsFinalOutputStageValid() const;
|
||||
bool HasFrameStage(CameraFrameStage stage) const;
|
||||
|
||||
@@ -60,6 +60,9 @@ CameraFramePlan CameraFramePlan::FromRequest(const CameraRenderRequest& request)
|
||||
plan.preScenePasses = request.preScenePasses;
|
||||
plan.postScenePasses = request.postScenePasses;
|
||||
plan.overlayPasses = request.overlayPasses;
|
||||
plan.shadowCasterStage.requested =
|
||||
request.shadowCaster.IsRequested() ||
|
||||
request.directionalShadow.IsValid();
|
||||
plan.colorChain.postProcess.requested = request.postProcess.IsRequested();
|
||||
plan.colorChain.finalOutput.requested = request.finalOutput.IsRequested();
|
||||
return plan;
|
||||
@@ -210,6 +213,25 @@ void CameraFramePlan::ClearFullscreenStage(
|
||||
RefreshGraphManagedSceneSurfaceState();
|
||||
}
|
||||
|
||||
bool CameraFramePlan::RequestShadowCasterStage(
|
||||
bool explicitlyConfigured) {
|
||||
shadowCasterStage.requested =
|
||||
shadowCaster.IsRequested() ||
|
||||
directionalShadow.IsValid();
|
||||
shadowCasterStage.explicitlyConfigured =
|
||||
shadowCasterStage.explicitlyConfigured ||
|
||||
explicitlyConfigured;
|
||||
return shadowCasterStage.requested;
|
||||
}
|
||||
|
||||
void CameraFramePlan::ClearShadowCasterStage(
|
||||
bool explicitlyConfigured) {
|
||||
shadowCasterStage.requested = false;
|
||||
shadowCasterStage.explicitlyConfigured =
|
||||
shadowCasterStage.explicitlyConfigured ||
|
||||
explicitlyConfigured;
|
||||
}
|
||||
|
||||
bool CameraFramePlan::HasExplicitFullscreenStageConfiguration(
|
||||
CameraFrameStage stage) const {
|
||||
if (const CameraFrameFullscreenStagePlan* fullscreenStagePlan =
|
||||
@@ -221,6 +243,14 @@ bool CameraFramePlan::HasExplicitFullscreenStageConfiguration(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CameraFramePlan::HasExplicitShadowCasterStageConfiguration() const {
|
||||
return shadowCasterStage.explicitlyConfigured;
|
||||
}
|
||||
|
||||
bool CameraFramePlan::IsShadowCasterStageRequested() const {
|
||||
return shadowCasterStage.requested;
|
||||
}
|
||||
|
||||
bool CameraFramePlan::IsPostProcessStageValid() const {
|
||||
if (!IsFullscreenStageRequested(CameraFrameStage::PostProcess)) {
|
||||
return true;
|
||||
@@ -286,7 +316,7 @@ bool CameraFramePlan::HasFrameStage(CameraFrameStage stage) const {
|
||||
|
||||
switch (GetCameraFrameStageRequestKind(stage)) {
|
||||
case CameraFrameStageRequestKind::ShadowCaster:
|
||||
return shadowCaster.IsRequested() || directionalShadow.IsValid();
|
||||
return IsShadowCasterStageRequested();
|
||||
case CameraFrameStageRequestKind::DepthOnly:
|
||||
return request.depthOnly.IsRequested();
|
||||
case CameraFrameStageRequestKind::ObjectId:
|
||||
|
||||
@@ -11,6 +11,10 @@ bool DirectionalShadowRuntime::ResolveExecutionState(
|
||||
const RenderPipeline& pipeline,
|
||||
DirectionalShadowExecutionState& outShadowState) {
|
||||
outShadowState = {};
|
||||
if (!plan.IsShadowCasterStageRequested()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
outShadowState.shadowCasterRequest = plan.shadowCaster;
|
||||
|
||||
if (outShadowState.shadowCasterRequest.IsRequested()) {
|
||||
|
||||
@@ -5882,6 +5882,29 @@ void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscr
|
||||
state->plan->ClearFullscreenStage(resolvedStage, true);
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedScriptableRenderPipelinePlanningContextState* const state =
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
|
||||
return state != nullptr &&
|
||||
state->plan != nullptr &&
|
||||
state->plan->RequestShadowCasterStage(true)
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedScriptableRenderPipelinePlanningContextState* const state =
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
|
||||
if (state == nullptr || state->plan == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->plan->ClearShadowCasterStage(true);
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing(
|
||||
uint64_t nativeHandle) {
|
||||
@@ -6098,6 +6121,8 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestFullscreenStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestFullscreenStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRenderedRequestCount", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetRenderedRequestCount));
|
||||
|
||||
@@ -210,7 +210,7 @@ set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES
|
||||
# Universal renderer package
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/CameraData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinGaussianSplatRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinVolumetricRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/DirectionalLightData.cs
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class BuiltinFinalColorPass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
public BuiltinFinalColorPass()
|
||||
{
|
||||
renderPassEvent =
|
||||
RenderPassEvent.BeforeRenderingFinalOutput;
|
||||
}
|
||||
|
||||
protected override bool RecordRenderGraph(
|
||||
ScriptableRenderContext context,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
return context != null &&
|
||||
renderingData != null &&
|
||||
renderingData.isFinalOutputStage &&
|
||||
(!renderingData.finalColorData.requiresProcessing ||
|
||||
RecordFinalColorFullscreenPass(
|
||||
context,
|
||||
renderingData.finalColorData.settings,
|
||||
"Universal.BuiltinFinalColor"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class BuiltinFinalColorPass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
public BuiltinFinalColorPass()
|
||||
{
|
||||
renderPassEvent =
|
||||
RenderPassEvent.BeforeRenderingFinalOutput;
|
||||
}
|
||||
|
||||
protected override bool RecordRenderGraph(
|
||||
ScriptableRenderContext context,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
return context != null &&
|
||||
renderingData != null &&
|
||||
renderingData.isFinalOutputStage &&
|
||||
(!renderingData.finalColorData.requiresProcessing ||
|
||||
RecordFinalColorFullscreenPass(
|
||||
context,
|
||||
renderingData.finalColorData.settings,
|
||||
"Universal.BuiltinFinalColor"));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BuiltinFinalColorRendererFeature
|
||||
: ScriptableRendererFeature
|
||||
{
|
||||
private BuiltinFinalColorPass m_pass;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_pass = new BuiltinFinalColorPass();
|
||||
}
|
||||
|
||||
public override void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null ||
|
||||
!context.HasFinalColorProcessing())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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.ClearFullscreenStage(
|
||||
CameraFrameStage.FinalOutput);
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.FinalOutput,
|
||||
finalOutputSource);
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null ||
|
||||
renderingData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderingData.isFinalOutputStage &&
|
||||
!renderingData.finalColorData.requiresProcessing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pass == null)
|
||||
{
|
||||
CreateInstance();
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(m_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,17 @@ namespace XCEngine.Rendering.Universal
|
||||
ClearDirectionalShadow(context);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearShadowCasterStage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace XCEngine.Rendering.Universal
|
||||
public sealed class UniversalRenderer : ScriptableRenderer
|
||||
{
|
||||
private readonly UniversalRendererData m_rendererData;
|
||||
private readonly BuiltinFinalColorPass m_builtinFinalColorPass =
|
||||
new BuiltinFinalColorPass();
|
||||
private readonly DrawObjectsPass m_drawOpaqueObjectsPass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.RenderOpaques,
|
||||
@@ -28,6 +30,18 @@ namespace XCEngine.Rendering.Universal
|
||||
rendererData ?? new UniversalRendererData();
|
||||
}
|
||||
|
||||
protected override void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigureShadowCasterStage(context);
|
||||
ConfigureFinalOutputStage(context);
|
||||
}
|
||||
|
||||
protected override void AddRenderPasses(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
@@ -53,6 +67,8 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
EnqueueTransparentPasses(mainScene);
|
||||
}
|
||||
|
||||
EnqueueFinalOutputPasses(renderingData);
|
||||
}
|
||||
|
||||
private void EnqueueOpaquePasses(
|
||||
@@ -84,5 +100,77 @@ namespace XCEngine.Rendering.Universal
|
||||
mainScene.transparentDrawingSettings);
|
||||
EnqueuePass(m_drawTransparentObjectsPass);
|
||||
}
|
||||
|
||||
private static void ConfigureShadowCasterStage(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context.IsStageRequested(
|
||||
CameraFrameStage.ShadowCaster))
|
||||
{
|
||||
context.RequestShadowCasterStage();
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearShadowCasterStage();
|
||||
}
|
||||
|
||||
private static void ConfigureFinalOutputStage(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.FinalOutput);
|
||||
if (!context.HasFinalColorProcessing())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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 void EnqueueFinalOutputPasses(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderingData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderingData.isFinalOutputStage &&
|
||||
!renderingData.finalColorData.requiresProcessing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnqueuePass(m_builtinFinalColorPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ namespace XCEngine.Rendering.Universal
|
||||
return new ScriptableRendererFeature[]
|
||||
{
|
||||
new BuiltinGaussianSplatRendererFeature(),
|
||||
new BuiltinVolumetricRendererFeature(),
|
||||
new BuiltinFinalColorRendererFeature()
|
||||
new BuiltinVolumetricRendererFeature()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,6 +522,16 @@ namespace XCEngine
|
||||
ulong nativeHandle,
|
||||
int stage);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern bool
|
||||
Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage(
|
||||
ulong nativeHandle);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void
|
||||
Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage(
|
||||
ulong nativeHandle);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern bool
|
||||
Rendering_ScriptableRenderPipelinePlanningContext_GetHasFinalColorProcessing(
|
||||
|
||||
@@ -66,6 +66,20 @@ namespace XCEngine.Rendering
|
||||
(int)stage);
|
||||
}
|
||||
|
||||
public bool RequestShadowCasterStage()
|
||||
{
|
||||
return InternalCalls
|
||||
.Rendering_ScriptableRenderPipelinePlanningContext_RequestShadowCasterStage(
|
||||
m_nativeHandle);
|
||||
}
|
||||
|
||||
public void ClearShadowCasterStage()
|
||||
{
|
||||
InternalCalls
|
||||
.Rendering_ScriptableRenderPipelinePlanningContext_ClearShadowCasterStage(
|
||||
m_nativeHandle);
|
||||
}
|
||||
|
||||
public bool HasFinalColorProcessing()
|
||||
{
|
||||
return InternalCalls
|
||||
|
||||
Reference in New Issue
Block a user