Add DA_RenderPipelineProfile and Platform Render Profiles documentation

- Introduced DA_RenderPipelineProfile data asset to define rendering pipeline configurations for various platforms and quality tiers.
- Documented enums, structs, variables, and default preset tables for render settings.
- Created a comprehensive developer guide for setting up platform-specific render profiles, including file structure, profile creation, and integration with upscalers.
- Included validation rules, console variable references, and testing matrices for ensuring compliance with platform requirements.
This commit is contained in:
Lefteris Notas
2026-05-22 18:10:24 +03:00
parent 14441c000c
commit dc9c1a6b98
19 changed files with 1449 additions and 83 deletions

View File

@@ -9,7 +9,7 @@
### Dependencies
- [`GI_GameFramework`](../01-core/04_GI_GameFramework.md) — Game instance reference
- [`BPC_PerformanceScaler`](../10-adaptive/69_BPC_PerformanceScaler.md) — Quality settings bridge
- [`BPC_RenderPipelineManager`](149_BPC_RenderPipelineManager.md) — Quality pipeline bridge (NEW)
- [`SS_SaveManager`](../05-saveload/28_SS_SaveManager.md) — Persist settings
- [`WBP_SettingsUI`](../06-ui/44_WBP_SettingsUI.md) — UI to read/write settings
@@ -116,8 +116,9 @@ Centralized settings manager that stores, applies, and persists all player-confi
[ApplySettings]
└─► ApplyGraphicsSettings():
Get "ResolutionScale", "ShadowQuality", etc.
Pass to BPC_PerformanceScaler.SetQualityLevel
Get "QualityPreset", "ResolutionScale", "UpscalerMethod", etc.
Pass to BPC_RenderPipelineManager.ApplyQualityPreset(QualityPreset)
→ RenderPipelineManager handles ALL CVars, reload detection, platform selection
└─► ApplyAudioSettings():
Get "MasterVolume", "SFXVolume", etc.
Pass to BPC_AudioManager volume modifiers
@@ -146,18 +147,31 @@ Centralized settings manager that stores, applies, and persists all player-confi
[RegisterDefaultSettings]
└─► Graphics category:
ResolutionScale Float 1.0 [0.51.5]
ShadowQuality Int 2 [03]
TextureQuality Int 2 [03]
PostProcessQuality Int 2 [03]
AntiAliasing Dropdown [TSR, TAA, FXAA, Off]
VSync Bool true
FrameRateLimit Int 60 [30240]
GlobalIllumination Dropdown [Lumen, SSGI, Off]
MotionBlur Bool true
DepthOfField Bool true
FoliageQuality Int 2 [03]
ViewDistance Int 2 [03]
QualityPreset Dropdown [Low, Medium, High, Ultra, Cinematic, Custom]
GlobalIllumination Dropdown [Lumen, Baked, SSGI, Off] ⚠ reload
ShadowMethod Dropdown [VSM, CSM, DFShadows, Off] ⚠ reload
ReflectionMethod Dropdown [Lumen, SSR, Captures, Off] ⚠ reload
MeshStrategy Dropdown [Nanite, LOD, Proxy] ⚠ reload
UpscalerMethod Dropdown [TSR, DLSS, FSR, PSSR, XeSS, NIS, TAAU, Off]
UpscalerQuality Dropdown [UltraPerf, Perf, Balanced, Quality, UltraQuality]
ResolutionScale Float 1.0 [0.252.0]
DynamicResolution Bool false
DynamicResTargetFPS Int 60 [30120]
ShadowQuality Int 2 [04]
TextureQuality Int 2 [03]
PostProcessQuality Int 2 [03]
ViewDistanceQuality Int 2 [03]
FoliageQuality Int 2 [03]
AntiAliasingQuality Int 2 [03]
VSync Bool true
FrameRateLimit Int 60 [30240]
MotionBlur Bool true
DepthOfField Bool true
VolumetricClouds Bool true
HW_RayTracing Bool false ⚠ reload
Brightness Float 1.0 [0.52.0]
HDR Bool false (if display supports)
TexturePoolSizeMB Int 2048 [5128192]
└─► Audio category:
MasterVolume Float 1.0 [01]
SFXVolume Float 1.0 [01]
@@ -205,7 +219,8 @@ Centralized settings manager that stores, applies, and persists all player-confi
| Target | Method | Why |
|--------|--------|-----|
| [`BPC_PerformanceScaler`](../10-adaptive/69_BPC_PerformanceScaler.md) | Cast to player | Graphics settings |
| [`BPC_RenderPipelineManager`](149_BPC_RenderPipelineManager.md) | Direct call | Graphics pipeline settings |
| [`BPC_PerformanceScaler`](../10-adaptive/69_BPC_PerformanceScaler.md) | Direct call | Adaptive quality bridging |
| [`BPC_AudioManager`](../10-adaptive/66_BPC_AudioManager.md) | Cast to player | Audio settings |
| [`BPC_Movement`](../02-player/14_BPC_Movement.md) | Cast to player | Gameplay settings |
| [`SS_SaveManager`](../05-saveload/28_SS_SaveManager.md) | Direct call | Persistence |

View File

@@ -0,0 +1,432 @@
# 149 — Render Pipeline Manager (`BPC_RenderPipelineManager`)
> **Blueprint-Only Implementation** — UE 5.55.7 supports all render pipeline configuration from Blueprints via `Execute Console Command` and `UGameUserSettings` API calls. This component wraps the complexity of per-platform render pipeline selection, upscaler configuration, and pre-level-load CVar application behind a simple `ApplyQualityPreset(PresetName)` interface.
---
## Purpose
Central authority for render pipeline configuration. Reads `DA_RenderPipelineProfile` Data Assets to determine the appropriate rendering method (Lumen vs Baked Lightmass), shadow system (VSM vs CSM), upscaler (DLSS/FSR/TSR/PSSR), and mesh strategy (Nanite vs LOD) for the current platform and quality preset. Applies settings via UE5 console variables, coordinates with `BPC_PerformanceScaler` for runtime quality tier adjustments, and broadcasts pipeline changes so dependent systems (Planar Capture, Audio, UI) can adapt.
## Dependencies
- **Requires:** [`DA_RenderPipelineProfile`](../14-data-assets/DA_RenderPipelineProfile.md) (render configs), [`SS_SettingsSystem`](105_SS_SettingsSystem.md) (saved quality preferences), [`GI_GameFramework`](../01-core/04_GI_GameFramework.md) (game phase for pre-load apply)
- **Required By:** [`BPC_PerformanceScaler`](../10-adaptive/91_BPC_PerformanceScaler.md) (delegates CVar application), [`SS_PlanarCaptureManager`](../17-capture/138_SS_PlanarCaptureManager.md) (capture quality cap on pipeline change), [`WBP_SettingsMenu`](../06-ui/57_WBP_SettingsMenu.md) (Video tab quality controls)
- **Engine/Plugin Requirements:** DLSS Plugin (optional), FSR Plugin (optional), XeSS Plugin (optional), GameplayTags, Enhanced Input
## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `ActorComponent` |
| **Class Type** | Blueprint Component |
| **Asset Path** | `Content/Framework/Settings/BPC_RenderPipelineManager` |
| **Implements Interfaces** | None |
| **Attachment** | Player Controller (`PC_CoreController`) |
---
## 1. Enums
*See [`DA_RenderPipelineProfile`](../14-data-assets/DA_RenderPipelineProfile.md) for: `ERenderPipelineMethod`, `EShadowMethod`, `EReflectionMethod`, `EUpscalerMethod`, `EMeshStrategy`, `EPlatformFamily`.*
### `ERenderPipelineChangeType`
| Value | Description |
|-------|-------------|
| `NonDestructive = 0` | Change is safe at runtime (resolution, texture quality, FPS cap) |
| `RequiresLevelReload = 1` | Change requires reloading the current level (GI method, Nanite, shadow method) |
| `RequiresEngineRestart = 2` | Change requires full engine restart (HWRT toggle on some platforms) |
---
## 2. Structs
### `SActivePipelineState`
| Field | Type | Description |
|-------|------|-------------|
| `Platform` | `EPlatformFamily` | Detected platform |
| `ActivePreset` | `FName` | Currently applied quality preset name |
| `PendingPreset` | `FName` | Queued preset awaiting reload |
| `ActivePipelineProfile` | `DA_RenderPipelineProfile` | Currently loaded profile Data Asset |
| `bPipelineApplied` | `bool` | Whether full pipeline has been applied |
| `bPendingReloadRequired` | `bool` | Whether a level reload is needed to apply changes |
| `AppliedConfig` | `SRenderPipelineConfig` | Currently active render config values |
---
## 3. Variables
### Configuration (Instance Editable)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `PlatformProfileMap` | `TMap<EPlatformFamily, DA_RenderPipelineProfile>` | `Empty` | `Config` | One Data Asset per platform family |
| `DefaultQualityPreset` | `FName` | `Medium` | `Config` | Preset to use on first launch |
| `bApplyPipelineOnBeginPlay` | `bool` | `true` | `Config` | Automatically apply pipeline on BeginPlay |
| `bAutoDetectPlatform` | `bool` | `true` | `Config` | Auto-detect platform at startup |
### Internal (Private)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `ActivePipeline` | `DA_RenderPipelineProfile` | `None` | `State` | Currently active profile |
| `ActiveState` | `SActivePipelineState` | — | `State` | Full current pipeline state |
| `DetectedPlatform` | `EPlatformFamily` | `PC_High` | `State` | Auto-detected platform |
| `bIsInitialized` | `bool` | `false` | `State` | Whether Initialize completed |
| `CachedPlayerController` | `APlayerController` | `None` | `Cache` | Owner PC reference |
| `bReloadNeededOnNextLevel` | `bool` | `false` | `State` | Reload flag for next level load |
---
## 4. Functions
### Public Functions
#### `Initialize` → `void`
- **Description:** Detects platform, loads the appropriate `DA_RenderPipelineProfile`, reads saved quality from `SS_SettingsSystem`, and applies initial pipeline settings.
- **Flow:**
1. Get Owner → Cast to PlayerController → cache
2. If `bAutoDetectPlatform`: call `DetectPlatform()` → set `DetectedPlatform`
3. Lookup `DA_RenderPipelineProfile` from `PlatformProfileMap` by `DetectedPlatform`
4. If not found: log error, fallback to `PC_High` profile
5. Read `SS_SettingsSystem.GetSettingFloat("QualityPreset")` → resolve preset name
6. If no saved setting: use `DefaultQualityPreset`
7. Call `ApplyQualityPreset(PresetName)`
8. Bind to `SS_SettingsSystem.OnSettingChanged` → listen for quality changes
9. Bind to `GI_GameFramework.OnGamePhaseChanged` → apply pending reloads on level change
10. Set `bIsInitialized = true`
11. Broadcast `OnPipelineManagerInitialized`
#### `ApplyQualityPreset` → `ERenderPipelineChangeType`
- **Description:** Apply a quality preset by name. Returns whether a level reload is needed.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `PresetName` | `FName` | Quality preset to apply ("Low", "Medium", "High", "Ultra", "Cinematic") |
| `bForceApply` | `bool` | Force re-apply even if already active |
- **Flow:**
1. Validate `bIsInitialized` and `ActivePipeline` is valid
2. Lookup `SRenderPipelineConfig` from `ActivePipeline.QualityPresets[PresetName]`
3. If not found: log error, return
4. Compare with `ActiveState.AppliedConfig`:
- If identical and not `bForceApply`: return `NonDestructive`
5. Determine change type:
- If `GIMethod`, `ShadowMethod`, or `MeshStrategy` changed → `RequiresLevelReload`
- Otherwise → `NonDestructive`
6. If `RequiresLevelReload` and game is mid-session:
- Store as `PendingPreset`, set `bReloadNeededOnNextLevel = true`
- Show UI notification "Settings will apply on next level load"
- Broadcast `OnPipelineReloadRequired`
- Return `RequiresLevelReload`
7. If safe to apply now: call `ApplyRenderConfig(PresetName, Config)`
8. Save to `SS_SettingsSystem.SetSetting("QualityPreset", PresetName)`
9. Broadcast `OnRenderPipelineChanged(PresetName, ChangeType)`
10. Return change type
#### `ApplyRenderConfig` → `void`
- **Description:** Executes console commands to apply a render configuration immediately.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `PresetName` | `FName` | Preset being applied |
| `Config` | `SRenderPipelineConfig` | Configuration to apply |
- **Flow:**
1. Execute console commands for GI method:
```
ExecuteConsoleCommand("r.DynamicGlobalIlluminationMethod {GIMethod}")
ExecuteConsoleCommand("r.Lumen.DiffuseIndirect.Allow {LumenAllowed}")
```
2. Execute shadow commands:
```
ExecuteConsoleCommand("r.Shadow.Virtual.Enable {VSMEnabled}")
ExecuteConsoleCommand("sg.ShadowQuality {ShadowQuality}")
```
3. Execute upscaling commands:
```
ExecuteConsoleCommand("r.ScreenPercentage {ResolutionScale*100}")
ExecuteConsoleCommand("r.TemporalAA.Upsampling {TSREnabled}")
// DLSS/FSR plugin-specific commands
```
4. Execute mesh/Nanite commands:
```
ExecuteConsoleCommand("r.Nanite {NaniteEnabled}")
ExecuteConsoleCommand("r.StaticMeshLODDistanceScale {LODScale}")
```
5. Execute scalability groups:
```
ExecuteConsoleCommand("sg.TextureQuality {TextureQuality}")
ExecuteConsoleCommand("sg.PostProcessQuality {PostProcessQuality}")
ExecuteConsoleCommand("sg.ViewDistanceQuality {ViewDistanceQuality}")
ExecuteConsoleCommand("sg.FoliageQuality {FoliageQuality}")
ExecuteConsoleCommand("sg.AntiAliasingQuality {AntiAliasingQuality}")
```
6. Execute post-process toggles:
```
ExecuteConsoleCommand("r.MotionBlurQuality {MotionBlur}")
ExecuteConsoleCommand("r.DepthOfFieldQuality {DoF}")
```
7. Execute platform-specific overrides from `SPlatformRenderDefaults.ConsoleVariables`
8. Set `ActiveState.AppliedConfig = Config`
9. Set `ActiveState.ActivePreset = PresetName`
10. Set `bReloadNeededOnNextLevel = false`
#### `ApplyPendingReload` → `void`
- **Description:** Called on level transition or game restart. Applies queued pipeline changes.
- **Flow:**
1. If `bReloadNeededOnNextLevel == false`: return
2. Get `SRenderPipelineConfig` for `ActiveState.PendingPreset`
3. Call `ApplyRenderConfig(PendingPreset, Config)`
4. Broadcast `OnRenderPipelineChanged(PendingPreset, RequiresLevelReload)`
#### `DetectPlatform` → `EPlatformFamily`
- **Description:** Auto-detect the current platform and GPU capability.
- **Flow:**
1. Check `UGameplayStatics::GetPlatformName()`:
- "PS5" → detect if Pro → `PS5_Pro` or `PS5`
- "PS4" → `PS4`
- "XboxOne" → `Xbox_One`
- "XSX" or "XboxSeries" → `Xbox_Series`
- "Switch" → `Switch`
- "Win64" → check GPU:
```cpp
IPlatformFile& PlatformFile = FPlatformFileManager::GetPlatformFile();
// Check GPU name via GRHIAdapterName
// RTX 2000+ / RX 6000+ → PC_High
// GTX 9001600 / iGPU → PC_Low
```
2. Store result in `DetectedPlatform`
3. Return platform
#### `SetUpscalerMethod` → `void`
- **Description:** Override the upscaler independently of quality preset.
- **Parameters:** `Method` (EUpscalerMethod), `Quality` (int32)
- **Flow:** Updates only the upscaler CVars without touching other settings.
#### `GetActiveUpscaler` → `EUpscalerMethod`
- **Description:** Returns the currently active upscaler. Read-only.
#### `GetActivePipelineConfig` → `SRenderPipelineConfig`
- **Description:** Returns a copy of the currently applied render config. Read-only.
#### `IsNaniteEnabled` → `bool`
- **Description:** Quick check if Nanite is currently active.
#### `IsLumenEnabled` → `bool`
- **Description:** Quick check if Lumen GI is currently active.
#### `RequiresReloadForPresetChange` → `bool`
- **Description:** Check if switching from current preset to a new one would require a level reload.
- **Parameters:** `NewPresetName` (FName)
#### `GetAvailableUpscalers` → `TArray<EUpscalerMethod>`
- **Description:** Returns which upscalers are available (based on installed plugins + platform).
#### `SetDynamicResolutionTarget` → `void`
- **Description:** Enable/disable dynamic resolution scaling.
- **Parameters:** `TargetFrameTimeMs` (float), `bEnabled` (bool)
---
## 5. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnPipelineManagerInitialized` | — | `Public` | Fired after Initialize completes |
| `OnRenderPipelineChanged` | `FName PresetName`, `ERenderPipelineChangeType ChangeType` | `Public` | Fired when pipeline configuration changes |
| `OnPipelineReloadRequired` | `FName PendingPreset` | `Public` | Fired when a change requires level reload — UI shows warning |
| `OnPipelineApplied` | `FName PresetName` | `Public` | Fired after all CVars have been executed |
| `OnUpscalerChanged` | `EUpscalerMethod NewMethod`, `int32 Quality` | `Public` | Fired when upscaler is changed |
| `OnPlatformDetected` | `EPlatformFamily Platform` | `Public` | Fired after platform detection |
---
## 6. Overridden Events
### Event: `BeginPlay`
- **Description:** Startup. Calls `Initialize()` then conditionally applies pipeline.
- **Flow:**
1. Call `Initialize()`
2. If `bApplyPipelineOnBeginPlay`: apply the default/saved preset
3. If game phase is `MainMenu` (not in-game): pipeline can be applied immediately (no reload warning needed)
### Event: `OnGamePhaseChanged` (bound to `GI_GameFramework`)
- **Description:** When transitioning from MainMenu to InGame or between levels, apply any pending pipeline changes.
- **Flow:**
1. If `bReloadNeededOnNextLevel`: call `ApplyPendingReload()`
2. Notify `SS_PlanarCaptureManager` of new pipeline state
---
## 7. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[BeginPlay / GI_GameFramework.OnGamePhaseChanged] --> B[Initialize]
B --> C[DetectPlatform]
C --> D[Load DA_RenderPipelineProfile for platform]
D --> E[Read saved QualityPreset from SS_SettingsSystem]
E --> F[ApplyQualityPreset PresetName]
G[User changes quality in settings] --> H[WBP_SettingsMenu → SS_SettingsSystem.SetSetting]
H --> I[SS_SettingsSystem.OnSettingChanged → BPC_RenderPipelineManager]
I --> J[ApplyQualityPreset NewPresetName]
J --> K{NonDestructive?}
K -->|Yes| L[ApplyRenderConfig immediately]
K -->|No - Needs Reload| M[Store as PendingPreset]
M --> N[Show UI Warning: 'Settings apply on next level']
M --> O[Broadcast OnPipelineReloadRequired]
L --> P[Broadcast OnRenderPipelineChanged]
Q[Level Transition / GamePhase change] --> R{Reload pending?}
R -->|Yes| S[ApplyPendingReload]
S --> T[ApplyRenderConfig with pending preset]
T --> P
P --> U[Notify SS_PlanarCaptureManager]
U --> V[PlanarCapture: adjust GlobalQualityCap]
```
---
## 8. Communication Matrix
| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `WBP_SettingsMenu` | `Indirect (SS_SettingsSystem)` | User selects quality preset → `SetSetting("QualityPreset", "High")` |
| `SS_SettingsSystem` | `Dispatcher` | `OnSettingChanged("QualityPreset")` → `BPC_RenderPipelineManager.ApplyQualityPreset()` |
| `BPC_PerformanceScaler` | `Function Call` | `BPC_RenderPipelineManager.ApplyQualityPreset()` for adaptive scaling |
| `BPC_RenderPipelineManager` | `Dispatcher` | `OnRenderPipelineChanged(PresetName)` → `SS_PlanarCaptureManager.AdjustGlobalQualityCap()` |
| `BPC_RenderPipelineManager` | `Dispatcher` | `OnPipelineReloadRequired(PendingPreset)` → `WBP_SettingsMenu.ShowReloadWarning()` |
| `SS_PlanarCaptureManager` | `Function Call` | `BPC_RenderPipelineManager.IsLumenEnabled()` — adjusts capture Lumen budget |
| `WBP_NotificationToast` | `Dispatcher` | `OnPipelineReloadRequired` → show "Settings will apply on next area" toast |
| `BPC_AudioAtmosphereController` | `Dispatcher` | `OnRenderPipelineChanged` → adjust audio quality budget |
---
## 9. Integration with Planar Capture System
When `BPC_RenderPipelineManager` applies a render pipeline change:
1. If Lumen is **disabled** (baked lightmass mode):
- `SS_PlanarCaptureManager` auto-caps `GlobalQualityCap` to `Medium` (no Hero tier Lumen captures)
- All `BPC_PlanarCapture` instances set `bEnableLumen = false` on their quality profiles
- Capture frame budget is increased (no Lumen overhead → can run more captures at higher FPS)
2. If Nanite is **disabled** (traditional LOD mode):
- Captures render faster (no Nanite rasterization overhead in capture pass)
- `SS_PlanarCaptureManager` can increase `GlobalQualityCap` by one tier
3. If upscaler is **active** (DLSS/FSR/TSR):
- Main view renders at lower internal resolution
- Planar captures render at configured quality tier resolution (independent of upscaler)
4. `BPC_PlanarCapture.ApplyQualityTier()` checks `BPC_RenderPipelineManager.IsLumenEnabled()`:
```
If !IsLumenEnabled() AND profile.bEnableLumen:
Force bEnableLumen = false // Prevent capture from trying to enable Lumen
```
---
## 10. Validation / Testing Checklist
- [ ] `DetectPlatform` correctly identifies PS5, PS4, Xbox Series, Xbox One, PC_High, PC_Low
- [ ] `ApplyQualityPreset("Low")` sets GI to None/Baked, switches to CSM, disables Nanite
- [ ] `ApplyQualityPreset("High")` sets GI to Lumen, switches to VSM, enables Nanite
- [ ] Switching from High→Low mid-game shows "requires level reload" warning
- [ ] Switching from High→Low in Main Menu applies immediately (no warning needed)
- [ ] Switching Low→High mid-game: PendingPreset stored, applies on next level load
- [ ] Planar capture budget adjusts: lower cap when Lumen is on, higher when off
- [ ] DLSS is available on PC_High with NVIDIA GPU — shows in `GetAvailableUpscalers()`
- [ ] FSR is available on all platforms — always in available list
- [ ] PSSR only available when `DetectedPlatform == PS5_Pro`
- [ ] NIS is available on Switch — fallback on non-NVIDIA PC
- [ ] `SetUpscalerMethod` independently changes upscaler without affecting other settings
- [ ] `GetActivePipelineConfig()` returns current state accurately after apply
- [ ] Edge case: `PlatformProfileMap` missing platform → logs error, falls back to `PC_High`
- [ ] Edge case: Invalid preset name → logs warning, no CVars changed
- [ ] Edge case: Console variable execution fails → logs error per failed CVar, continues
- [ ] Edge case: Hot-swap GPU (eGPU) → `DetectPlatform` called again, pipeline may change
---
## 11. Manual Implementation Guide
### 11.1 Class Setup
1. Create Blueprint Class: parent `ActorComponent`, name `BPC_RenderPipelineManager`
2. Path: `Content/Framework/Settings/`
3. Add all variables, enums, structs, and event dispatchers from this spec
### 11.2 Key UE5 Nodes
| Node | Where to Find | Used For |
|------|---------------|----------|
| `Execute Console Command` | Right-click → "Execute Console Command" | Applying all CVar changes |
| `Get Platform Name` | Right-click → "Get Platform Name" | Platform detection |
| `Get Game User Settings` | Right-click → "Get Game User Settings" | Accessing scalability API |
| `Set Overall Scalability Level` | On GameUserSettings | Bulk quality tier application |
| `Get Game Instance` → `Get Subsystem(SS_SettingsSystem)` | Subsystem access | Reading/writing quality setting |
| `Get Game Instance` → `Get Subsystem(SS_PlanarCaptureManager)` | Subsystem access | Adjust capture budget |
| `Switch on EPlatformFamily` | Right-click → "Switch" | Platform-specific logic |
| `Make SRenderPipelineConfig` | Right-click → "Make Struct" | Building config structs |
### 11.3 Node-by-Node: ApplyRenderConfig
```
[Function: ApplyRenderConfig(PresetName, Config)]
Step 1: Get Owner → Cast to PlayerController → cache
Step 2: Break SRenderPipelineConfig → get all fields
Step 3: Switch on Config.GIMethod:
Lumen_GI → ExecuteConsoleCommand("r.DynamicGlobalIlluminationMethod 1")
ExecuteConsoleCommand("r.Lumen.Reflections.Allow 1")
Baked_Lightmass → ExecuteConsoleCommand("r.DynamicGlobalIlluminationMethod 0")
ExecuteConsoleCommand("r.Lumen.Reflections.Allow 0")
SSGI → ExecuteConsoleCommand("r.DynamicGlobalIlluminationMethod 2")
None → ExecuteConsoleCommand("r.DynamicGlobalIlluminationMethod 0")
Step 4: ExecuteConsoleCommand("r.Shadow.Virtual.Enable {VSM?1:0}")
Step 5: ExecuteConsoleCommand("sg.ShadowQuality {ShadowQuality}")
Step 6: ExecuteConsoleCommand("r.ScreenPercentage {ResolutionScale*100}")
Step 7: Switch on Config.Upscaler:
TSR → ExecuteConsoleCommand("r.TemporalAA.Upsampling 1")
DLSS → ExecuteConsoleCommand("r.NGX.DLSS.Enable 1")
ExecuteConsoleCommand("r.NGX.DLSS.Quality {UpscalerQuality}")
FSR → ExecuteConsoleCommand("r.FidelityFX.FSR2.Enabled 1")
NIS → ExecuteConsoleCommand("r.NIS.Enable 1")
Step 8: ExecuteConsoleCommand("r.Nanite {NaniteEnabled?1:0}")
Step 9: Execute Console Command "sg.TextureQuality {TextureQuality}"
Execute Console Command "sg.PostProcessQuality {PostProcessQuality}"
Execute Console Command "sg.ViewDistanceQuality {ViewDistanceQuality}"
Execute Console Command "sg.FoliageQuality {FoliageQuality}"
Step 10: ExecuteConsoleCommand("r.MotionBlurQuality {MotionBlur?2:0}")
Step 11: ExecuteConsoleCommand("r.DepthOfFieldQuality {DoF?2:0}")
Step 12: Set ActiveState.AppliedConfig = Config
Step 13: Set ActiveState.ActivePreset = PresetName
Step 14: Set bReloadNeededOnNextLevel = false
Step 15: Broadcast OnPipelineApplied(PresetName)
```
### 11.4 Networking
- **Local client only.** Render pipeline is per-client hardware. No replication.
- On listen servers: the server-host player runs their own render pipeline; other clients run theirs.
---
## 12. Blueprint Build Checklist
- [ ] Create Blueprint class: `BPC_RenderPipelineManager` (parent: `ActorComponent`)
- [ ] Add enums: `ERenderPipelineMethod`, `EShadowMethod`, `EReflectionMethod`, `EUpscalerMethod`, `EMeshStrategy`, `EPlatformFamily`, `ERenderPipelineChangeType`
- [ ] Add structs: `SRenderPipelineConfig`, `SPlatformRenderDefaults`, `SActivePipelineState`
- [ ] Add all variables from Section 3
- [ ] Build `BeginPlay` → `Initialize` chain
- [ ] Implement `DetectPlatform` with Switch on Platform Name
- [ ] Implement `ApplyQualityPreset` with reload detection logic
- [ ] Implement `ApplyRenderConfig` with full CVar execution
- [ ] Implement `ApplyPendingReload` bound to `GI_GameFramework.OnGamePhaseChanged`
- [ ] Implement `SetUpscalerMethod` / `GetAvailableUpscalers` / `IsLumenEnabled` / `IsNaniteEnabled`
- [ ] Create all 6 event dispatchers
- [ ] Bind to `SS_SettingsSystem.OnSettingChanged` (QualityPreset key)
- [ ] Bind to `GI_GameFramework.OnGamePhaseChanged`
- [ ] Create at least one `DA_RenderPipelineProfile` instance per target platform
- [ ] Test: Low preset disables Lumen, Nanite, switches to CSM
- [ ] Test: High preset enables Lumen, Nanite, VSM
- [ ] Test: Mid-session pipeline switch shows reload warning
- [ ] Test: Main Menu pipeline switch applies immediately
- [ ] Test: Planar capture quality cap adjusts on pipeline change
---
*Blueprint Spec: Render Pipeline Manager. Conforms to TEMPLATE.md v2.0 — part of the UE5 Modular Game Framework, SETTINGS layer.*