diff --git a/docs/plan/SRP_Universal默认ScenePass数据化计划_2026-04-20.md b/docs/plan/SRP_Universal默认ScenePass数据化计划_2026-04-20.md new file mode 100644 index 00000000..ad1997aa --- /dev/null +++ b/docs/plan/SRP_Universal默认ScenePass数据化计划_2026-04-20.md @@ -0,0 +1,125 @@ +# SRP Universal 默认 Scene Pass 数据化计划 2026-04-20 + +## 1. 阶段目标 + +把 `UniversalRenderer` 里写死的默认主场景 pass 顺序抽到 `UniversalRendererData` 一侧,让这一层开始具备真正的 renderer-data 驱动组织能力。 + +这一阶段完成后,要达到的状态是: + +1. `UniversalRenderer` 不再直接硬编码 opaque / skybox / transparent 全套默认 pass 成员 +2. `UniversalRendererData` 不再只是三个布尔开关,而是能描述默认 scene pass 序列 +3. renderer 负责“解释并执行 data”,而不是继续兼任“存放默认拓扑定义” +4. 后续继续做 Unity 风格的 renderer preset、renderer variant、SRP 包层扩展时,有稳定落点 + +## 2. 当前问题 + +现在的主要问题不是 draw primitive 不够,而是默认 renderer 组织仍然过于硬编码: + +1. `UniversalRenderer` 直接持有 before/after opaque、skybox、transparent 这些 pass 实例 +2. `UniversalRendererData` 只有 `renderOpaque / renderSkybox / renderTransparent` +3. 默认主场景拓扑并没有正式进入 renderer data 层 + +这会带来几个后果: + +1. renderer data 无法真正承载“这个 renderer 默认长什么样” +2. 后续做 renderer preset、多个 renderer variant 时,会继续把逻辑堆在 renderer 类本身 +3. Unity 风格的 `RendererData -> Renderer` 关系虽然已经搭起来了,但默认 pass 组织还没真正归位 + +## 3. 本阶段范围 + +本阶段只做默认主场景 pass 的数据化,不做新的高级渲染能力扩展。 + +包括: + +1. 新增一个最小可用的 `UniversalScenePassData` +2. 让 `UniversalRendererData` 用默认 scene pass 数组表达主场景默认序列 +3. 让 `UniversalRenderer` 按 data 创建/配置/执行默认 pass +4. 保持现有默认行为不变,确保旧场景不回退 +5. 重编译 `XCEditor` +6. 运行旧版 `editor/bin/Debug/XCEngine.exe` 冒烟至少 10 秒 + +不包括: + +1. deferred renderer +2. shadow 包层迁移 +3. post-process renderer preset 扩展 +4. 用户级 renderer inspector/asset 编辑器 + +## 4. 设计原则 + +这一步不做一套脱离 Unity 的“任意图编辑器”。 + +采用的原则是: + +1. 只把默认 scene pass 的 ownership 从 renderer 类搬到 renderer data +2. 保持 pass 类型仍然是 Unity 式的 injection / draw renderers / draw skybox +3. 保留现有 `RendererFeature` 作为扩展层,不让 feature 重新承担默认拓扑 +4. renderer 中只保留运行时 pass cache 和执行逻辑 + +## 5. 实施步骤 + +### Step 1:建立默认 Scene Pass 数据模型 + +新增一个短名类型,至少表达: + +1. pass 类型 +2. `RenderPassEvent` +3. injection point +4. scene draw phase +5. `RendererListDesc` +6. `DrawingSettings` +7. 是否启用 + +### Step 2:让 UniversalRendererData 持有默认 Scene Pass 序列 + +把原先三个布尔开关替换成明确的默认序列,默认仍然是: + +1. BeforeOpaque injection +2. Opaque draw +3. AfterOpaque injection +4. BeforeSkybox injection +5. Skybox draw +6. AfterSkybox injection +7. BeforeTransparent injection +8. Transparent draw +9. AfterTransparent injection + +### Step 3:把 UniversalRenderer 改成 data 解释器 + +renderer 需要: + +1. 从 `UniversalRendererData` 读取默认 scene pass 数组 +2. 维护每个 slot 对应的 runtime pass 实例 +3. 根据 data 重新配置 draw/injection/skybox pass +4. 把启用的 pass enqueue 进当前帧 + +### Step 4:编译与冒烟验证 + +固定验证流程: + +1. `cmake --build . --config Debug --target XCEditor` +2. 启动 `editor/bin/Debug/XCEngine.exe` +3. 冒烟至少 10 秒 +4. 检查 `editor/bin/Debug/editor.log` 最新时间与 `SceneReady` + +## 6. 验收标准 + +本阶段收口后必须满足: + +1. `UniversalRenderer` 默认主场景 pass 不再硬编码为字段阵列 +2. `UniversalRendererData` 可以完整表达默认主场景 pass 顺序 +3. 现有 opaque / skybox / transparent 默认行为保持一致 +4. `XCEditor` 编译通过 +5. 旧 editor 冒烟通过 + +## 7. 阶段意义 + +这一步收口之后,SRP 主线会从: + +`Asset -> RendererData -> Renderer` 结构已经存在,但默认主场景拓扑还黏在 renderer 类里 + +推进到: + +`Asset -> RendererData(默认拓扑) -> Renderer(执行器)` + +这才是真正可以继续往 Unity 风格 SRP/URP 走的下一跳。 diff --git a/managed/CMakeLists.txt b/managed/CMakeLists.txt index 4a023522..7cebec6c 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/UniversalScenePassData.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipeline.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs ${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs diff --git a/managed/GameScripts/RenderPipelineApiProbe.cs b/managed/GameScripts/RenderPipelineApiProbe.cs index 700bad89..dc8d7581 100644 --- a/managed/GameScripts/RenderPipelineApiProbe.cs +++ b/managed/GameScripts/RenderPipelineApiProbe.cs @@ -2537,9 +2537,24 @@ namespace Gameplay { new UniversalRendererData { - renderOpaque = true, - renderSkybox = false, - renderTransparent = false + defaultScenePasses = + new UniversalScenePassData[] + { + UniversalScenePassData + .CreateInjection( + RenderPassEvent.BeforeRenderingOpaques, + SceneRenderInjectionPoint.BeforeOpaque), + UniversalScenePassData + .CreateDrawRenderers( + RenderPassEvent.RenderOpaques, + SceneRenderPhase.Opaque, + RendererListDesc.CreateDefault( + RendererListType.Opaque)), + UniversalScenePassData + .CreateInjection( + RenderPassEvent.AfterRenderingOpaques, + SceneRenderInjectionPoint.AfterOpaque) + } } } }; diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/CameraData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/CameraData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/CameraData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/CameraData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/ColorScalePostProcessRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs similarity index 70% rename from managed/XCEngine.ScriptCore/Rendering/Universal/ColorScalePostProcessRendererFeature.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs index 9b0bb879..85043c3c 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Universal/ColorScalePostProcessRendererFeature.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs @@ -20,13 +20,22 @@ namespace XCEngine.Rendering.Universal ScriptableRenderContext context, RenderingData renderingData) { - return context != null && - renderingData != null && - renderingData.isPostProcessStage && - m_feature != null && - RecordColorScaleFullscreenPass( - context, - m_feature.colorScale); + if (context == null || + renderingData == null || + !renderingData.isPostProcessStage || + m_feature == null || + !context.sourceColorTexture.isValid || + !context.primaryColorTarget.isValid) + { + return false; + } + + return context + .AddRasterPass("Universal.ColorScalePostProcess") + .UseColorSource(context.sourceColorTexture) + .SetColorAttachment(context.primaryColorTarget) + .SetColorScaleFullscreenExecution(m_feature.colorScale) + .Commit(); } } diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/DirectionalLightData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DirectionalLightData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/DirectionalLightData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DirectionalLightData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/DirectionalShadowData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DirectionalShadowData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/DirectionalShadowData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DirectionalShadowData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/DisableDirectionalShadowRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DisableDirectionalShadowRendererFeature.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/DisableDirectionalShadowRendererFeature.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DisableDirectionalShadowRendererFeature.cs diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs index ca8e195f..b91ef3d2 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/DrawSkyboxPass.cs @@ -8,6 +8,12 @@ namespace XCEngine.Rendering.Universal public DrawSkyboxPass( RenderPassEvent passEvent = RenderPassEvent.RenderSkybox) + { + Configure(passEvent); + } + + public void Configure( + RenderPassEvent passEvent) { renderPassEvent = passEvent; } diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/EnvironmentData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/EnvironmentData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/EnvironmentData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/EnvironmentData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/FinalColorData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/FinalColorData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/FinalColorData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/FinalColorData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/LightingData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/LightingData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/LightingData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/LightingData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RenderClearFlags.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderClearFlags.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RenderClearFlags.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderClearFlags.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RenderEnvironmentMode.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderEnvironmentMode.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RenderEnvironmentMode.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderEnvironmentMode.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RenderPassEvent.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderPassEvent.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RenderPassEvent.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderPassEvent.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RendererBackedRenderPipeline.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RendererBackedRenderPipeline.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RendererBackedRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RendererBackedRenderPipelineAsset.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RendererCameraRequestContext.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RendererCameraRequestContext.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RendererDrivenRenderPipeline.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererDrivenRenderPipeline.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RendererDrivenRenderPipeline.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererDrivenRenderPipeline.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RendererRecordingContext.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RendererRecordingContext.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RenderingData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RenderingData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/RenderingDataResolver.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingDataResolver.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/RenderingDataResolver.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderingDataResolver.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderer.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRendererData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRendererFeature.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/ShadowData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ShadowData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/ShadowData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ShadowData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/StageColorData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/StageColorData.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/StageColorData.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/StageColorData.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderPipeline.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipeline.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderPipeline.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipeline.cs diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs similarity index 100% rename from managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderPipelineAsset.cs rename to managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs index 195ace9e..be3ee594 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs @@ -1,3 +1,4 @@ +using System; using XCEngine; using XCEngine.Rendering; @@ -5,11 +6,20 @@ namespace XCEngine.Rendering.Universal { internal sealed class UniversalSceneInjectionPass : ScriptableRenderPass { - private readonly SceneRenderInjectionPoint m_injectionPoint; + private SceneRenderInjectionPoint m_injectionPoint; public UniversalSceneInjectionPass( RenderPassEvent passEvent, SceneRenderInjectionPoint injectionPoint) + { + Configure( + passEvent, + injectionPoint); + } + + public void Configure( + RenderPassEvent passEvent, + SceneRenderInjectionPoint injectionPoint) { renderPassEvent = passEvent; m_injectionPoint = injectionPoint; @@ -30,44 +40,8 @@ namespace XCEngine.Rendering.Universal public sealed class UniversalRenderer : ScriptableRenderer { private readonly UniversalRendererData m_rendererData; - private readonly UniversalSceneInjectionPass m_beforeOpaquePass = - new UniversalSceneInjectionPass( - RenderPassEvent.BeforeRenderingOpaques, - SceneRenderInjectionPoint.BeforeOpaque); - private readonly DrawObjectsPass m_drawOpaqueObjectsPass = - new DrawObjectsPass( - RenderPassEvent.RenderOpaques, - SceneRenderPhase.Opaque, - RendererListDesc.CreateDefault( - RendererListType.Opaque)); - private readonly UniversalSceneInjectionPass m_afterOpaquePass = - new UniversalSceneInjectionPass( - RenderPassEvent.AfterRenderingOpaques, - SceneRenderInjectionPoint.AfterOpaque); - private readonly UniversalSceneInjectionPass m_beforeSkyboxPass = - new UniversalSceneInjectionPass( - RenderPassEvent.BeforeRenderingSkybox, - SceneRenderInjectionPoint.BeforeSkybox); - private readonly DrawSkyboxPass m_drawSkyboxPass = - new DrawSkyboxPass(); - private readonly UniversalSceneInjectionPass m_afterSkyboxPass = - new UniversalSceneInjectionPass( - RenderPassEvent.AfterRenderingSkybox, - SceneRenderInjectionPoint.AfterSkybox); - private readonly UniversalSceneInjectionPass m_beforeTransparentPass = - new UniversalSceneInjectionPass( - RenderPassEvent.BeforeRenderingTransparents, - SceneRenderInjectionPoint.BeforeTransparent); - private readonly DrawObjectsPass m_drawTransparentObjectsPass = - new DrawObjectsPass( - RenderPassEvent.RenderTransparents, - SceneRenderPhase.Transparent, - RendererListDesc.CreateDefault( - RendererListType.Transparent)); - private readonly UniversalSceneInjectionPass m_afterTransparentPass = - new UniversalSceneInjectionPass( - RenderPassEvent.AfterRenderingTransparents, - SceneRenderInjectionPoint.AfterTransparent); + private ScriptableRenderPass[] m_defaultScenePasses = + Array.Empty(); public UniversalRenderer( UniversalRendererData rendererData) @@ -85,25 +59,129 @@ namespace XCEngine.Rendering.Universal return; } - if (m_rendererData.renderOpaque) + UniversalScenePassData[] scenePasses = + m_rendererData + .GetDefaultScenePassesInstance(); + EnsureDefaultScenePassCache(scenePasses); + + for (int i = 0; i < scenePasses.Length; ++i) { - EnqueuePass(m_beforeOpaquePass); - EnqueuePass(m_drawOpaqueObjectsPass); - EnqueuePass(m_afterOpaquePass); + UniversalScenePassData scenePass = + scenePasses[i]; + if (scenePass == null || + !scenePass.isEnabled) + { + continue; + } + + ScriptableRenderPass renderPass = + ConfigureDefaultScenePass( + i, + scenePass); + if (renderPass != null) + { + EnqueuePass(renderPass); + } + } + } + + private void EnsureDefaultScenePassCache( + UniversalScenePassData[] scenePasses) + { + int passCount = + scenePasses != null + ? scenePasses.Length + : 0; + if (m_defaultScenePasses.Length == passCount) + { + return; } - if (m_rendererData.renderSkybox) + ScriptableRenderPass[] resizedPasses = + new ScriptableRenderPass[passCount]; + int copyCount = + Math.Min( + m_defaultScenePasses.Length, + passCount); + for (int i = 0; i < copyCount; ++i) { - EnqueuePass(m_beforeSkyboxPass); - EnqueuePass(m_drawSkyboxPass); - EnqueuePass(m_afterSkyboxPass); + resizedPasses[i] = + m_defaultScenePasses[i]; } - if (m_rendererData.renderTransparent) + m_defaultScenePasses = resizedPasses; + } + + private ScriptableRenderPass ConfigureDefaultScenePass( + int passIndex, + UniversalScenePassData scenePass) + { + if (scenePass == null || + passIndex < 0 || + passIndex >= m_defaultScenePasses.Length) { - EnqueuePass(m_beforeTransparentPass); - EnqueuePass(m_drawTransparentObjectsPass); - EnqueuePass(m_afterTransparentPass); + return null; + } + + ScriptableRenderPass renderPass = + m_defaultScenePasses[passIndex]; + switch (scenePass.passType) + { + case UniversalScenePassType.Injection: + UniversalSceneInjectionPass injectionPass = + renderPass as UniversalSceneInjectionPass; + if (injectionPass == null) + { + injectionPass = + new UniversalSceneInjectionPass( + scenePass.passEvent, + scenePass.injectionPoint); + m_defaultScenePasses[passIndex] = + injectionPass; + } + + injectionPass.Configure( + scenePass.passEvent, + scenePass.injectionPoint); + return injectionPass; + case UniversalScenePassType.DrawRenderers: + DrawObjectsPass drawObjectsPass = + renderPass as DrawObjectsPass; + if (drawObjectsPass == null) + { + drawObjectsPass = + new DrawObjectsPass( + scenePass.passEvent, + scenePass.scenePhase, + scenePass.rendererListDesc, + scenePass.drawingSettings); + m_defaultScenePasses[passIndex] = + drawObjectsPass; + } + + drawObjectsPass.Configure( + scenePass.passEvent, + scenePass.scenePhase, + scenePass.rendererListDesc, + scenePass.drawingSettings); + return drawObjectsPass; + case UniversalScenePassType.DrawSkybox: + DrawSkyboxPass drawSkyboxPass = + renderPass as DrawSkyboxPass; + if (drawSkyboxPass == null) + { + drawSkyboxPass = + new DrawSkyboxPass( + scenePass.passEvent); + m_defaultScenePasses[passIndex] = + drawSkyboxPass; + } + + drawSkyboxPass.Configure( + scenePass.passEvent); + return drawSkyboxPass; + default: + return null; } } } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs new file mode 100644 index 00000000..1ea94424 --- /dev/null +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs @@ -0,0 +1,82 @@ +using System; +using XCEngine; +using XCEngine.Rendering; + +namespace XCEngine.Rendering.Universal +{ + public class UniversalRendererData : ScriptableRendererData + { + public UniversalScenePassData[] defaultScenePasses; + public ScriptableRendererFeature[] rendererFeatures; + + public UniversalRendererData() + { + defaultScenePasses = CreateDefaultScenePasses(); + rendererFeatures = + Array.Empty(); + } + + protected override ScriptableRenderer CreateRenderer() + { + return new UniversalRenderer(this); + } + + protected override ScriptableRendererFeature[] CreateRendererFeatures() + { + return rendererFeatures ?? + Array.Empty(); + } + + protected override string GetPipelineRendererAssetKey() + { + return "BuiltinForward"; + } + + internal UniversalScenePassData[] GetDefaultScenePassesInstance() + { + if (defaultScenePasses == null) + { + defaultScenePasses = CreateDefaultScenePasses(); + } + + return defaultScenePasses; + } + + public static UniversalScenePassData[] CreateDefaultScenePasses() + { + return new[] + { + UniversalScenePassData.CreateInjection( + RenderPassEvent.BeforeRenderingOpaques, + SceneRenderInjectionPoint.BeforeOpaque), + UniversalScenePassData.CreateDrawRenderers( + RenderPassEvent.RenderOpaques, + SceneRenderPhase.Opaque, + RendererListDesc.CreateDefault( + RendererListType.Opaque)), + UniversalScenePassData.CreateInjection( + RenderPassEvent.AfterRenderingOpaques, + SceneRenderInjectionPoint.AfterOpaque), + UniversalScenePassData.CreateInjection( + RenderPassEvent.BeforeRenderingSkybox, + SceneRenderInjectionPoint.BeforeSkybox), + UniversalScenePassData.CreateDrawSkybox(), + UniversalScenePassData.CreateInjection( + RenderPassEvent.AfterRenderingSkybox, + SceneRenderInjectionPoint.AfterSkybox), + UniversalScenePassData.CreateInjection( + RenderPassEvent.BeforeRenderingTransparents, + SceneRenderInjectionPoint.BeforeTransparent), + UniversalScenePassData.CreateDrawRenderers( + RenderPassEvent.RenderTransparents, + SceneRenderPhase.Transparent, + RendererListDesc.CreateDefault( + RendererListType.Transparent)), + UniversalScenePassData.CreateInjection( + RenderPassEvent.AfterRenderingTransparents, + SceneRenderInjectionPoint.AfterTransparent) + }; + } + } +} + diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalScenePassData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalScenePassData.cs new file mode 100644 index 00000000..1a3161cb --- /dev/null +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalScenePassData.cs @@ -0,0 +1,81 @@ +using XCEngine; +using XCEngine.Rendering; + +namespace XCEngine.Rendering.Universal +{ + public enum UniversalScenePassType + { + Injection, + DrawRenderers, + DrawSkybox + } + + public sealed class UniversalScenePassData + { + public bool isEnabled = true; + public UniversalScenePassType passType = + UniversalScenePassType.Injection; + public RenderPassEvent passEvent = + RenderPassEvent.BeforeRenderingOpaques; + public SceneRenderInjectionPoint injectionPoint = + SceneRenderInjectionPoint.BeforeOpaque; + public SceneRenderPhase scenePhase = + SceneRenderPhase.Opaque; + public RendererListDesc rendererListDesc = + RendererListDesc.CreateDefault( + RendererListType.Opaque); + public DrawingSettings drawingSettings = + DrawingSettings.CreateDefault(); + + public static UniversalScenePassData CreateInjection( + RenderPassEvent passEvent, + SceneRenderInjectionPoint injectionPoint) + { + return new UniversalScenePassData + { + passType = UniversalScenePassType.Injection, + passEvent = passEvent, + injectionPoint = injectionPoint + }; + } + + public static UniversalScenePassData CreateDrawRenderers( + RenderPassEvent passEvent, + SceneRenderPhase scenePhase, + RendererListDesc rendererListDesc) + { + return CreateDrawRenderers( + passEvent, + scenePhase, + rendererListDesc, + DrawingSettings.CreateDefault()); + } + + public static UniversalScenePassData CreateDrawRenderers( + RenderPassEvent passEvent, + SceneRenderPhase scenePhase, + RendererListDesc rendererListDesc, + DrawingSettings drawingSettings) + { + return new UniversalScenePassData + { + passType = UniversalScenePassType.DrawRenderers, + passEvent = passEvent, + scenePhase = scenePhase, + rendererListDesc = rendererListDesc, + drawingSettings = drawingSettings + }; + } + + public static UniversalScenePassData CreateDrawSkybox( + RenderPassEvent passEvent = + RenderPassEvent.RenderSkybox) + { + return new UniversalScenePassData + { + passType = UniversalScenePassType.DrawSkybox, + passEvent = passEvent + }; + } + } +} diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderPass.cs b/managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderPass.cs deleted file mode 100644 index 9c9c8fbb..00000000 --- a/managed/XCEngine.ScriptCore/Rendering/Universal/ScriptableRenderPass.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System; -using XCEngine; -using XCEngine.Rendering; - -namespace XCEngine.Rendering.Universal -{ - public abstract class ScriptableRenderPass - { - private enum RecordedScenePhase - { - Opaque = 0, - Skybox = 1, - Transparent = 3 - } - - private enum RecordedSceneInjectionPoint - { - BeforeOpaque = 0, - AfterOpaque = 1, - BeforeSkybox = 2, - AfterSkybox = 3, - BeforeTransparent = 4, - AfterTransparent = 5 - } - - private enum RecordedFullscreenPassType - { - ColorScale = 0, - ShaderVector = 1 - } - - 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) - { - return RecordFullscreenPassInternal( - context, - RecordedFullscreenPassType.ColorScale, - string.Empty, - string.Empty, - colorScale); - } - - 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)); - } - - return RecordFullscreenPassInternal( - context, - RecordedFullscreenPassType.ShaderVector, - shaderPath, - passName ?? string.Empty, - vectorPayload); - } - - 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 bool RecordFullscreenPassInternal( - ScriptableRenderContext context, - RecordedFullscreenPassType passType, - string shaderPath, - string passName, - Vector4 vectorPayload) - { - return context != null && - InternalCalls - .Rendering_ScriptableRenderContext_RecordFullscreenPass( - context.nativeHandle, - (int)passType, - shaderPath, - passName, - ref vectorPayload); - } - } -} - diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderer.cs b/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderer.cs deleted file mode 100644 index 25e6b2b8..00000000 --- a/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRenderer.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using XCEngine; -using XCEngine.Rendering; - -namespace XCEngine.Rendering.Universal -{ - internal enum UniversalSceneRecordingKind - { - BeforeOpaqueInjection, - OpaqueScene, - AfterOpaqueInjection, - BeforeSkyboxInjection, - SkyboxScene, - AfterSkyboxInjection, - BeforeTransparentInjection, - TransparentScene, - AfterTransparentInjection - } - - internal sealed class UniversalSceneRecordingPass : ScriptableRenderPass - { - private readonly UniversalSceneRecordingKind m_recordingKind; - - public UniversalSceneRecordingPass( - RenderPassEvent passEvent, - UniversalSceneRecordingKind recordingKind) - { - renderPassEvent = passEvent; - m_recordingKind = recordingKind; - } - - protected override bool RecordRenderGraph( - ScriptableRenderContext context, - RenderingData renderingData) - { - return context != null && - renderingData != null && - renderingData.isMainSceneStage && - 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; - } - } - } - - internal sealed class UniversalSceneFeature : ScriptableRendererFeature - { - private readonly UniversalRendererData m_rendererData; - private readonly UniversalSceneRecordingPass m_beforeOpaquePass = - new UniversalSceneRecordingPass( - RenderPassEvent.BeforeRenderingOpaques, - UniversalSceneRecordingKind.BeforeOpaqueInjection); - private readonly UniversalSceneRecordingPass m_opaquePass = - new UniversalSceneRecordingPass( - RenderPassEvent.RenderOpaques, - UniversalSceneRecordingKind.OpaqueScene); - private readonly UniversalSceneRecordingPass m_afterOpaquePass = - new UniversalSceneRecordingPass( - RenderPassEvent.AfterRenderingOpaques, - UniversalSceneRecordingKind.AfterOpaqueInjection); - private readonly UniversalSceneRecordingPass m_beforeSkyboxPass = - new UniversalSceneRecordingPass( - RenderPassEvent.BeforeRenderingSkybox, - UniversalSceneRecordingKind.BeforeSkyboxInjection); - private readonly UniversalSceneRecordingPass m_skyboxPass = - new UniversalSceneRecordingPass( - RenderPassEvent.RenderSkybox, - UniversalSceneRecordingKind.SkyboxScene); - private readonly UniversalSceneRecordingPass m_afterSkyboxPass = - new UniversalSceneRecordingPass( - RenderPassEvent.AfterRenderingSkybox, - UniversalSceneRecordingKind.AfterSkyboxInjection); - private readonly UniversalSceneRecordingPass m_beforeTransparentPass = - new UniversalSceneRecordingPass( - RenderPassEvent.BeforeRenderingTransparents, - UniversalSceneRecordingKind.BeforeTransparentInjection); - private readonly UniversalSceneRecordingPass m_transparentPass = - new UniversalSceneRecordingPass( - RenderPassEvent.RenderTransparents, - UniversalSceneRecordingKind.TransparentScene); - private readonly UniversalSceneRecordingPass m_afterTransparentPass = - new UniversalSceneRecordingPass( - RenderPassEvent.AfterRenderingTransparents, - UniversalSceneRecordingKind.AfterTransparentInjection); - - public UniversalSceneFeature( - UniversalRendererData rendererData) - { - 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); - } - } - } - - public sealed class UniversalRenderer : ScriptableRenderer - { - public UniversalRenderer( - UniversalRendererData rendererData) - { - UniversalRendererData resolvedData = - rendererData ?? new UniversalRendererData(); - AddFeature(new UniversalSceneFeature(resolvedData)); - } - } -} - diff --git a/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRendererData.cs b/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRendererData.cs deleted file mode 100644 index dc2bad8d..00000000 --- a/managed/XCEngine.ScriptCore/Rendering/Universal/UniversalRendererData.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using XCEngine; -using XCEngine.Rendering; - -namespace XCEngine.Rendering.Universal -{ - public class UniversalRendererData : ScriptableRendererData - { - public bool renderOpaque = true; - public bool renderSkybox = true; - public bool renderTransparent = true; - public ScriptableRendererFeature[] rendererFeatures = - Array.Empty(); - - protected override ScriptableRenderer CreateRenderer() - { - return new UniversalRenderer(this); - } - - protected override ScriptableRendererFeature[] CreateRendererFeatures() - { - return rendererFeatures ?? - Array.Empty(); - } - - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForward"; - } - } -} - diff --git a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs index 571ad704..8f2657c7 100644 --- a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs +++ b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs @@ -1,3 +1,4 @@ +using System; using System.Reflection; using XCEngine; using XCEngine.Rendering; @@ -128,9 +129,8 @@ namespace ProjectScripts { new UniversalRendererData { - renderOpaque = false, - renderSkybox = false, - renderTransparent = false, + defaultScenePasses = + Array.Empty(), rendererFeatures = new ScriptableRendererFeature[] { new RenderObjectsRendererFeature