From e123e584c8f975d7eda25de84a484fc232d5fbee Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 21 Apr 2026 00:53:35 +0800 Subject: [PATCH] feat(srp): add camera-driven universal renderer selection --- ...erSelection主链计划_完成归档_2026-04-21.md | 124 ++++++++++++++++++ .../Rendering/Planning/CameraRenderRequest.h | 1 + .../XCEngine/Rendering/RenderPipeline.h | 1 + .../CameraFrameGraph/StageContract.cpp | 2 + .../src/Scripting/Mono/MonoScriptRuntime.cpp | 63 +++++++++ managed/CMakeLists.txt | 1 + .../Universal/RendererBackedRenderPipeline.cs | 5 +- .../RendererBackedRenderPipelineAsset.cs | 62 ++++++++- .../Universal/RendererCameraRequestContext.cs | 21 +++ .../Universal/RendererRecordingContext.cs | 3 + .../Rendering/Universal/RenderingData.cs | 8 ++ .../UniversalAdditionalCameraData.cs | 18 +++ .../Universal/UniversalRenderPipelineAsset.cs | 21 +++ managed/XCEngine.ScriptCore/InternalCalls.cs | 26 ++++ .../Core/CameraRenderRequestContext.cs | 32 +++++ .../Rendering/Core/ScriptableRenderContext.cs | 5 + ...ScriptableRenderPipelinePlanningContext.cs | 5 + 17 files changed, 391 insertions(+), 7 deletions(-) create mode 100644 docs/used/SRP_UniversalRendererSelection主链计划_完成归档_2026-04-21.md create mode 100644 managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalAdditionalCameraData.cs diff --git a/docs/used/SRP_UniversalRendererSelection主链计划_完成归档_2026-04-21.md b/docs/used/SRP_UniversalRendererSelection主链计划_完成归档_2026-04-21.md new file mode 100644 index 00000000..f8f28b5c --- /dev/null +++ b/docs/used/SRP_UniversalRendererSelection主链计划_完成归档_2026-04-21.md @@ -0,0 +1,124 @@ +# SRP Universal Renderer Selection 主链计划 2026-04-21 + +## 1. 阶段目标 + +把当前 Universal 的 renderer list / default renderer index 从“资产层有配置,但运行时基本只吃默认 renderer”的状态,收成真正可执行的 Unity 风格 renderer selection 主链。 + +本阶段完成后,要达到: + +1. `RendererBackedRenderPipelineAsset` 不再在 request / plan / execution 三处各自偷偷取默认 renderer +2. 相机级 renderer 选择能够在 request 阶段被正式解析,并沿着 frame plan 一路传到 execution +3. Universal 能像 Unity URP 一样,先支持“相机覆盖 renderer index”这条最关键的链路 +4. 后续继续做 renderer inspector、多 renderer、deferred renderer 时,不需要再返工主链 + +## 2. 当前问题 + +当前已经有: + +1. `rendererDataList` +2. `defaultRendererIndex` +3. `GetRenderer(index)` / `GetRendererData(index)` + +但是主链仍然不完整: + +1. `ConfigureCameraRenderRequest()` 默认只下发到 default renderer data +2. `ConfigureCameraFramePlan()` 默认只下发到 default renderer data +3. `RendererBackedRenderPipeline.ResolveRenderer(...)` 录制阶段也只拿 default renderer +4. 没有正式“当前 camera 这一帧最终选中了哪个 renderer index”的 request / plan / context 数据 + +这意味着: + +1. renderer list 现在更多只是配置壳,不是运行时 contract +2. 以后想做 Unity 风格不同 renderer(Forward Renderer / 2D Renderer / 自定义 Renderer)时,主链会重新散掉 +3. 即便后面加 `UniversalAdditionalCameraData`,也没有稳定的数据路径把选择结果带到 execution + +## 3. 设计原则 + +这一阶段按 Unity 的职责分层来收: + +1. camera 侧决定是否覆盖 renderer index +2. pipeline asset 负责解析“这一帧这个 camera 应该用哪个 renderer” +3. request / frame plan / render context 负责携带“已解析好的 renderer index” +4. renderer data / renderer / feature 只吃解析结果,不自己再猜 + +也就是: + +`camera override -> request.rendererIndex -> plan.rendererIndex -> execution resolve renderer` + +## 4. 本阶段范围 + +包括: + +1. 给 native `CameraRenderRequest` 增加正式 `rendererIndex` +2. 给 managed request / planning / render context 暴露当前 renderer index +3. 让 `RendererBackedRenderPipelineAsset` 统一通过“已解析 renderer index”选择 renderer data / renderer +4. 给 Universal 增加最小版 `UniversalAdditionalCameraData` +5. 让 `UniversalRenderPipelineAsset` 支持相机覆盖 renderer index +6. 重编译 `XCEditor` +7. 运行旧版 `editor/bin/Debug/XCEngine.exe` 冒烟至少 10 秒 + +不包括: + +1. 多 backend renderer 混挂 +2. renderer inspector UI +3. deferred renderer +4. camera stack / overlay renderer 体系 +5. 完整 Unity `CameraData.renderer` / `cameraData.camera` API 还原 + +## 5. 实施步骤 + +### Step 1:把 renderer selection 结果正式写进 request / plan / context + +做这几件事: + +1. native `CameraRenderRequest` 增加 `rendererIndex` +2. managed `CameraRenderRequestContext` 增加 `camera` 和 `rendererIndex` +3. managed planning / render context 增加只读 `rendererIndex` + +目标是让 selection 结果不再是执行时临时猜出来,而是 request 阶段就正式落下。 + +### Step 2:统一 RendererBackedRenderPipelineAsset 的 renderer resolve 入口 + +把现在这些默认 renderer 路径统一起来: + +1. `ConfigureCameraRenderRequest` +2. `ConfigureCameraFramePlan` +3. `ResolveRenderer` + +要求: + +1. request 阶段先解析 renderer index +2. 后续 plan / execution 全部吃这个结果 +3. default fallback 规则只有一套 + +### Step 3:补 Universal 的 camera override seam + +新增: + +1. `UniversalAdditionalCameraData` +2. `UniversalRenderPipelineAsset` 对相机 `rendererIndex` 覆盖的解析逻辑 + +先只做最小可用版: + +1. `rendererIndex = -1` 表示使用 pipeline default renderer +2. `rendererIndex >= 0` 表示请求指定 renderer slot +3. 越界仍然回退 default renderer + +### Step 4:编译与冒烟 + +固定流程: + +1. `cmake --build . --config Debug --target XCEditor` +2. 启动 `editor/bin/Debug/XCEngine.exe` +3. 冒烟至少 10 秒 +4. 检查 `editor/bin/Debug/editor.log` + +## 6. 验收标准 + +本阶段收口后必须满足: + +1. Universal renderer list 不再只是配置壳,而是正式进入 request / plan / execution 主链 +2. `RendererBackedRenderPipelineAsset` 的 renderer 选择规则唯一 +3. camera 可以正式覆盖 renderer index,并稳定回退 default renderer +4. `XCEditor` 编译通过 +5. 旧 editor 冒烟通过 diff --git a/engine/include/XCEngine/Rendering/Planning/CameraRenderRequest.h b/engine/include/XCEngine/Rendering/Planning/CameraRenderRequest.h index 4eb2f723..ca31f2f4 100644 --- a/engine/include/XCEngine/Rendering/Planning/CameraRenderRequest.h +++ b/engine/include/XCEngine/Rendering/Planning/CameraRenderRequest.h @@ -29,6 +29,7 @@ struct CameraRenderRequest { ObjectIdRenderRequest objectId; float cameraDepth = 0.0f; uint8_t cameraStackOrder = 0; + int32_t rendererIndex = -1; RenderClearFlags clearFlags = RenderClearFlags::All; bool hasClearColorOverride = false; Math::Color clearColorOverride = Math::Color::Black(); diff --git a/engine/include/XCEngine/Rendering/RenderPipeline.h b/engine/include/XCEngine/Rendering/RenderPipeline.h index c857faf0..6fae6c75 100644 --- a/engine/include/XCEngine/Rendering/RenderPipeline.h +++ b/engine/include/XCEngine/Rendering/RenderPipeline.h @@ -50,6 +50,7 @@ struct RenderPipelineStageRenderGraphContext { CameraFrameColorSource::ExplicitSurface; bool usesGraphManagedOutputColor = false; DirectionalShadowRenderPlan directionalShadowPlan = {}; + int32_t rendererIndex = -1; }; class RenderPipelineRenderer; diff --git a/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp b/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp index 12229260..bf4b8e05 100644 --- a/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp +++ b/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp @@ -597,6 +597,8 @@ RenderPipelineStageRenderGraphContext BuildCameraFramePipelineStageRenderGraphCo context.plan.UsesGraphManagedOutputColor(stageState.stage); pipelineContext.directionalShadowPlan = context.plan.directionalShadow; + pipelineContext.rendererIndex = + context.plan.request.rendererIndex; return pipelineContext; } diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index 3ff6b8b3..816b21b5 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -3908,6 +3908,16 @@ int32_t InternalCall_Rendering_ScriptableRenderContext_GetStage( : static_cast(Rendering::CameraFrameStage::MainScene); } +int32_t InternalCall_Rendering_ScriptableRenderContext_GetRendererIndex( + uint64_t nativeHandle) { + const ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + return state != nullptr && + state->graphContext != nullptr + ? state->graphContext->rendererIndex + : -1; +} + int32_t InternalCall_Rendering_ScriptableRenderContext_GetSourceColorTextureHandle( uint64_t nativeHandle) { const ManagedScriptableRenderContextState* const state = @@ -4833,6 +4843,43 @@ InternalCall_Rendering_CameraRenderRequestContext_GetRenderedRequestCount( : 0; } +uint64_t +InternalCall_Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID( + uint64_t nativeHandle) { + const ManagedCameraRenderRequestContextState* const state = + FindManagedCameraRenderRequestContextState(nativeHandle); + if (state == nullptr || + state->request == nullptr || + state->request->camera == nullptr || + state->request->camera->GetGameObject() == nullptr) { + return 0u; + } + + return state->request->camera->GetGameObject()->GetUUID(); +} + +int32_t InternalCall_Rendering_CameraRenderRequestContext_GetRendererIndex( + uint64_t nativeHandle) { + const ManagedCameraRenderRequestContextState* const state = + FindManagedCameraRenderRequestContextState(nativeHandle); + return state != nullptr && + state->request != nullptr + ? state->request->rendererIndex + : -1; +} + +void InternalCall_Rendering_CameraRenderRequestContext_SetRendererIndex( + uint64_t nativeHandle, + int32_t rendererIndex) { + ManagedCameraRenderRequestContextState* const state = + FindManagedCameraRenderRequestContextState(nativeHandle); + if (state == nullptr || state->request == nullptr) { + return; + } + + state->request->rendererIndex = rendererIndex; +} + mono_bool InternalCall_Rendering_CameraRenderRequestContext_GetHasDirectionalShadow( uint64_t nativeHandle) { @@ -4856,6 +4903,17 @@ void InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow( state->request->directionalShadow = {}; } +int32_t +InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex( + uint64_t nativeHandle) { + const ManagedScriptableRenderPipelinePlanningContextState* const state = + FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle); + return state != nullptr && + state->plan != nullptr + ? state->plan->request.rendererIndex + : -1; +} + mono_bool InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested( uint64_t nativeHandle, @@ -5094,6 +5152,7 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_SetRenderPipelineAsset", reinterpret_cast(&InternalCall_Rendering_SetRenderPipelineAsset)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_GetRenderPipelineAsset", reinterpret_cast(&InternalCall_Rendering_GetRenderPipelineAsset)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStage", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetStage)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetRendererIndex", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetRendererIndex)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetSourceColorTextureHandle", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetSourceColorTextureHandle)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetDepthTargetHandle", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_GetDepthTargetHandle)); @@ -5160,6 +5219,7 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordScenePhase", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_RecordScenePhase)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_DrawRenderersByDesc", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordSceneInjectionPoint", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_RecordSceneInjectionPoint)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetStageColorSource", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageColorSource)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_GetStageUsesGraphManagedOutputColor)); @@ -5167,6 +5227,9 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFullscreenStage)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_GetRenderedBaseCameraCount)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRenderedRequestCount", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_GetRenderedRequestCount)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetRendererIndex", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_GetRendererIndex)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetRendererIndex", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_SetRendererIndex)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetHasDirectionalShadow", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_GetHasDirectionalShadow)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_ClearDirectionalShadow", reinterpret_cast(&InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow)); diff --git a/managed/CMakeLists.txt b/managed/CMakeLists.txt index 5b0853c5..a5b35fd3 100644 --- a/managed/CMakeLists.txt +++ b/managed/CMakeLists.txt @@ -234,6 +234,7 @@ set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/StageColorData.cs + ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalAdditionalCameraData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalMainSceneData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipeline.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs index dd623e70..70640f7d 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs @@ -17,7 +17,10 @@ namespace XCEngine.Rendering.Universal RendererRecordingContext context) { return m_asset != null - ? m_asset.ResolveSelectedRenderer() + ? m_asset.ResolveRenderer( + context != null + ? context.rendererIndex + : -1) : null; } } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs index 91d9cdd7..ec1d5df7 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs @@ -25,11 +25,21 @@ namespace XCEngine.Rendering.Universal protected override void ConfigureCameraRenderRequest( CameraRenderRequestContext context) { + ApplyResolvedRendererIndex( + context, + ResolveRendererIndex(context)); + ConfigureRendererCameraRequest( new RendererCameraRequestContext(context)); + ApplyResolvedRendererIndex( + context, + context != null + ? context.rendererIndex + : -1); + ScriptableRendererData resolvedRendererData = - ResolveSelectedRendererData(); + ResolveRendererData(context); if (resolvedRendererData != null) { resolvedRendererData @@ -42,7 +52,7 @@ namespace XCEngine.Rendering.Universal ScriptableRenderPipelinePlanningContext context) { ScriptableRendererData resolvedRendererData = - ResolveSelectedRendererData(); + ResolveRendererData(context); if (resolvedRendererData != null) { resolvedRendererData @@ -100,6 +110,12 @@ namespace XCEngine.Rendering.Universal { } + protected virtual int ResolveRendererIndex( + CameraRenderRequestContext context) + { + return ResolveSelectedRendererIndex(); + } + protected virtual ScriptableRendererData CreateDefaultRendererData() { @@ -135,10 +151,11 @@ namespace XCEngine.Rendering.Universal int rendererIndex) { return ResolveRendererDataByResolvedIndex( - ResolveRendererIndex(rendererIndex)); + ResolveRendererIndexWithFallback( + rendererIndex)); } - internal ScriptableRenderer GetRenderer( + internal ScriptableRenderer ResolveRenderer( int rendererIndex) { ScriptableRendererData rendererData = @@ -255,10 +272,43 @@ namespace XCEngine.Rendering.Universal private int ResolveSelectedRendererIndex() { - return ResolveRendererIndex(defaultRendererIndex); + return ResolveRendererIndexWithFallback( + defaultRendererIndex); } - private int ResolveRendererIndex( + private ScriptableRendererData ResolveRendererData( + CameraRenderRequestContext context) + { + return GetRendererData( + context != null + ? context.rendererIndex + : -1); + } + + private ScriptableRendererData ResolveRendererData( + ScriptableRenderPipelinePlanningContext context) + { + return GetRendererData( + context != null + ? context.rendererIndex + : -1); + } + + private void ApplyResolvedRendererIndex( + CameraRenderRequestContext context, + int rendererIndex) + { + if (context == null) + { + return; + } + + context.rendererIndex = + ResolveRendererIndexWithFallback( + rendererIndex); + } + + private int ResolveRendererIndexWithFallback( int rendererIndex) { EnsureRendererDataList(); diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs index cbd849ad..58d33d1b 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs @@ -1,3 +1,4 @@ +using XCEngine; using XCEngine.Rendering; namespace XCEngine.Rendering.Universal @@ -22,6 +23,26 @@ namespace XCEngine.Rendering.Universal ? m_requestContext.renderedRequestCount : 0; + public Camera camera => + m_requestContext != null + ? m_requestContext.camera + : null; + + public int rendererIndex + { + get => + m_requestContext != null + ? m_requestContext.rendererIndex + : -1; + set + { + if (m_requestContext != null) + { + m_requestContext.rendererIndex = value; + } + } + } + internal CameraRenderRequestContext requestContext => m_requestContext; } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs index 8b26b988..ee4f3408 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs @@ -42,6 +42,9 @@ namespace XCEngine.Rendering.Universal public RenderingData renderingData => m_renderingData; + public int rendererIndex => + m_renderingData.rendererIndex; + internal ScriptableRenderContext renderContext => m_renderContext; } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingData.cs index c0453e7d..6b5c7feb 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingData.cs @@ -8,6 +8,7 @@ namespace XCEngine.Rendering.Universal internal RenderingData(CameraFrameStage stage) : this( stage, + -1, CameraData.Default, LightingData.Default, ShadowData.Default, @@ -22,6 +23,9 @@ namespace XCEngine.Rendering.Universal context != null ? context.stage : CameraFrameStage.MainScene, + context != null + ? context.rendererIndex + : -1, context != null ? RenderingDataResolver.ResolveCameraData(context) : CameraData.Default, @@ -45,6 +49,7 @@ namespace XCEngine.Rendering.Universal private RenderingData( CameraFrameStage stage, + int rendererIndex, CameraData cameraData, LightingData lightingData, ShadowData shadowData, @@ -53,6 +58,7 @@ namespace XCEngine.Rendering.Universal StageColorData stageColorData) { this.stage = stage; + this.rendererIndex = rendererIndex; this.cameraData = cameraData ?? CameraData.Default; this.lightingData = lightingData ?? LightingData.Default; @@ -68,6 +74,8 @@ namespace XCEngine.Rendering.Universal public CameraFrameStage stage { get; } + public int rendererIndex { get; } + public CameraData cameraData { get; } public LightingData lightingData { get; } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalAdditionalCameraData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalAdditionalCameraData.cs new file mode 100644 index 00000000..b30ca382 --- /dev/null +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalAdditionalCameraData.cs @@ -0,0 +1,18 @@ +using XCEngine; + +namespace XCEngine.Rendering.Universal +{ + public sealed class UniversalAdditionalCameraData + : MonoBehaviour + { + public int rendererIndex = -1; + + public bool hasRendererOverride => + rendererIndex >= 0; + + public void ResetRenderer() + { + rendererIndex = -1; + } + } +} diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs index 4458fc47..11d64448 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs @@ -17,6 +17,27 @@ namespace XCEngine.Rendering.Universal { return new UniversalRendererData(); } + + protected override int ResolveRendererIndex( + CameraRenderRequestContext context) + { + Camera camera = + context != null + ? context.camera + : null; + if (camera != null) + { + UniversalAdditionalCameraData additionalCameraData = + camera.GetComponent(); + if (additionalCameraData != null && + additionalCameraData.hasRendererOverride) + { + return additionalCameraData.rendererIndex; + } + } + + return base.ResolveRendererIndex(context); + } } } diff --git a/managed/XCEngine.ScriptCore/InternalCalls.cs b/managed/XCEngine.ScriptCore/InternalCalls.cs index 3abdb1bf..8fc9468f 100644 --- a/managed/XCEngine.ScriptCore/InternalCalls.cs +++ b/managed/XCEngine.ScriptCore/InternalCalls.cs @@ -389,6 +389,11 @@ namespace XCEngine internal static extern int Rendering_ScriptableRenderContext_GetStage( ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderContext_GetRendererIndex( + ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int Rendering_ScriptableRenderContext_GetSourceColorTextureHandle( @@ -473,6 +478,11 @@ namespace XCEngine ulong nativeHandle, ulong rasterPassHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex( + ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderPipelinePlanningContext_IsStageRequested( @@ -802,6 +812,22 @@ namespace XCEngine Rendering_CameraRenderRequestContext_GetRenderedRequestCount( ulong nativeHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern ulong + Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int + Rendering_CameraRenderRequestContext_GetRendererIndex( + ulong nativeHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void + Rendering_CameraRenderRequestContext_SetRendererIndex( + ulong nativeHandle, + int rendererIndex); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_CameraRenderRequestContext_GetHasDirectionalShadow( diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/CameraRenderRequestContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/CameraRenderRequestContext.cs index 85232bac..e7bad149 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/CameraRenderRequestContext.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/CameraRenderRequestContext.cs @@ -21,6 +21,38 @@ namespace XCEngine.Rendering .Rendering_CameraRenderRequestContext_GetRenderedRequestCount( m_nativeHandle); + public Camera camera + { + get + { + ulong cameraGameObjectUUID = + InternalCalls + .Rendering_CameraRenderRequestContext_GetCameraGameObjectUUID( + m_nativeHandle); + if (cameraGameObjectUUID == 0) + { + return null; + } + + GameObject gameObject = + new GameObject(cameraGameObjectUUID); + return gameObject.GetComponent(); + } + } + + public int rendererIndex + { + get => + InternalCalls + .Rendering_CameraRenderRequestContext_GetRendererIndex( + m_nativeHandle); + set => + InternalCalls + .Rendering_CameraRenderRequestContext_SetRendererIndex( + m_nativeHandle, + value); + } + internal ulong nativeHandle => m_nativeHandle; } diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs index 3eac56e4..d6c0ac51 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs @@ -15,6 +15,11 @@ namespace XCEngine.Rendering (CameraFrameStage)InternalCalls.Rendering_ScriptableRenderContext_GetStage( m_nativeHandle); + public int rendererIndex => + InternalCalls + .Rendering_ScriptableRenderContext_GetRendererIndex( + m_nativeHandle); + public RenderGraphTextureHandle sourceColorTexture => RenderGraphTextureHandle.FromNativeIndex( InternalCalls diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelinePlanningContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelinePlanningContext.cs index e2955b8e..5a04d085 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelinePlanningContext.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelinePlanningContext.cs @@ -12,6 +12,11 @@ namespace XCEngine.Rendering m_nativeHandle = nativeHandle; } + public int rendererIndex => + InternalCalls + .Rendering_ScriptableRenderPipelinePlanningContext_GetRendererIndex( + m_nativeHandle); + public bool IsStageRequested( CameraFrameStage stage) {