refactor(srp): move core stage defaults into universal renderer

This commit is contained in:
2026-04-21 15:44:19 +08:00
parent 6a538d0d2e
commit f2be5627be
14 changed files with 408 additions and 111 deletions

View File

@@ -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 演进做准备。

View File

@@ -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` 拆分做好结构准备

View File

@@ -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;

View File

@@ -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:

View File

@@ -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()) {

View File

@@ -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));

View File

@@ -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

View File

@@ -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"));
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -14,6 +14,17 @@ namespace XCEngine.Rendering.Universal
ClearDirectionalShadow(context);
}
}
public override void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null)
{
return;
}
context.ClearShadowCasterStage();
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -74,8 +74,7 @@ namespace XCEngine.Rendering.Universal
return new ScriptableRendererFeature[]
{
new BuiltinGaussianSplatRendererFeature(),
new BuiltinVolumetricRendererFeature(),
new BuiltinFinalColorRendererFeature()
new BuiltinVolumetricRendererFeature()
};
}
}

View File

@@ -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(

View File

@@ -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