# Platform Render Profiles — Developer Guide

**Version:** 1.0 | **Target UE:** 5.5–5.7 | **Systems:** BPC_RenderPipelineManager (149) + DA_RenderPipelineProfile

---

## Purpose

This guide covers setting up per-platform render pipeline configurations in a UE5 project using the Modular Game Framework's render profile system. It explains how to configure Lumen vs baked lighting, Nanite vs traditional LODs, shadow systems, upscalers, and platform-specific constraints — all driven by `DA_RenderPipelineProfile` Data Assets.

---

## Core Concept

UE5's rendering pipeline features (Lumen GI, Nanite, Virtual Shadow Maps) are **not runtime-switchable** — they must be set before the engine initializes or before a level loads. The framework's solution:

1. **Data Asset** (`DA_RenderPipelineProfile`) — Defines render configs per quality tier per platform
2. **Manager** (`BPC_RenderPipelineManager`) — Reads profiles, applies CVars, handles reload requirements
3. **Settings** (`SS_SettingsSystem`) — Persists player's quality choice
4. **UI** (`WBP_SettingsMenu`) — Exposes quality controls with warnings for destructive changes

---

## 1. Creating DA_RenderPipelineProfile Instances

### File Structure
```
Content/Game/DataAssets/RenderProfiles/
├── DA_RPP_PS5.uasset              ← PlayStation 5 profile
├── DA_RPP_PS5_Pro.uasset          ← PS5 Pro (PSSR support)
├── DA_RPP_PS4.uasset              ← PS4 / PS4 Pro
├── DA_RPP_Xbox_Series.uasset      ← Xbox Series X|S
├── DA_RPP_Xbox_One.uasset         ← Xbox One / One X
├── DA_RPP_PC_High.uasset          ← PC: RTX 2000+ / RX 6000+
├── DA_RPP_PC_Low.uasset           ← PC: GTX 900-1600 / iGPU
├── DA_RPP_SteamDeck.uasset        ← Steam Deck
├── DA_RPP_Switch.uasset           ← Nintendo Switch
└── DA_RPP_Switch_2.uasset          ← Switch 2 (future)
```

### Profile Creation Walkthrough (PS5 Example)

1. Content Browser → `Content/Game/DataAssets/RenderProfiles/`
2. Right-click → **Miscellaneous → Data Asset**
3. Select class: `DA_RenderPipelineProfile`
4. Name: `DA_RPP_PS5`
5. Open the asset, configure:

**Platform Defaults:**
| Field | Value |
|-------|-------|
| `Platform` | `PS5` |
| `DefaultQualityPreset` | `Medium` |
| `SupportedPipelines` | `[Lumen_GI, Baked_Lightmass, SSGI]` |
| `SupportedUpscalers` | `[TSR, PSSR, FSR]` |
| `MaxResolutionScale` | `1.0` |
| `MaxFPS` | `120` |
| `VRAMBudget_MB` | `14336` |
| `bSupportsNanite` | `true` |
| `bSupportsLumen` | `true` |
| `bSupportsHWRT` | `true` |

**Quality Presets:**
Add 5 entries to the `QualityPresets` map:

| Key (FName) | Config |
|-------------|--------|
| `Low` | GIMethod=Baked, Shadow=CSM, Reflection=Captures, Upscaler=TSR(Perf), Mesh=LOD, Resolution=0.70, FPS=60 |
| `Medium` | GIMethod=Lumen_Low, Shadow=VSM_Low, Reflection=Lumen_Low, Upscaler=TSR(Balanced), Mesh=Nanite, Resolution=0.85, FPS=60 |
| `High` | GIMethod=Lumen_High, Shadow=VSM_High, Reflection=Lumen_High, Upscaler=TSR(Quality), Mesh=Nanite, Resolution=1.0, FPS=60 |
| `Ultra` | GIMethod=Lumen_Ultra, Shadow=VSM_Ultra, Reflection=Lumen_Ultra, Upscaler=PSSR, Mesh=Nanite, Resolution=1.0, FPS=60 |
| `Cinematic` | GIMethod=Lumen+HWRT, Shadow=VSM+RT, Reflection=Lumen+RT, Upscaler=PSSR, Mesh=Nanite, Resolution=1.0, FPS=30 |

**Key detail:** The "Low" preset uses `bRequiresLevelReload = true` because it switches from Lumen→Baked and Nanite→LOD. Medium→High does NOT require reload (both use Lumen+Nanite, only quality differs).

---

## 2. Render Pipeline Method Decision Tree

```
START: Which platform is the player on?
│
├─ PS5 / Xbox Series / PC_High
│   ├─ Player chooses "Low" → Baked Lightmass + CSM + LOD meshes
│   │   └─ Goal: 60 FPS on base console, 120 FPS on Pro/PC
│   ├─ Player chooses "Medium/High" → Lumen + VSM + Nanite
│   │   └─ Goal: 60 FPS at 85-100% resolution
│   └─ Player chooses "Ultra/Cinematic" → Lumen + HWRT + Nanite + PSSR/DLSS
│       └─ Goal: Max quality, 30-60 FPS
│
├─ PS4 / Xbox_One
│   └─ ALL presets → Baked Lightmass + CSM + LOD meshes
│       └─ These platforms do NOT support Lumen/Nanite
│       └─ Upscaler: TAAU (built-in, lightweight)
│       └─ Goal: 30 FPS at 60-90% resolution
│
├─ Switch
│   └─ ALL presets → Baked Lightmass + CSM + ProxyGeometry/LOD
│       └─ Upscaler: NIS (lightweight) or FSR
│       └─ Goal: 30 FPS at 40-70% resolution (docked) / 30 FPS at 30-55% (handheld)
│
└─ SteamDeck
    └─ Low/Medium → Baked/SSGI + CSM + LOD
    └─ High → SSGI + CSM + LOD
    └─ Upscaler: FSR
    └─ Goal: 40-60 FPS at 70-85% resolution
```

---

## 3. Upscaler Integration Guide

### 3.1 Available Upscalers and Requirements

| Upscaler | Plugin Required | Platforms | Quality | Notes |
|----------|----------------|-----------|---------|-------|
| **TSR** (Temporal Super Resolution) | Built-in UE5 | ALL | Good | Default choice. No plugin needed. Works everywhere. |
| **DLSS 3** | NVIDIA DLSS Plugin | PC (RTX 2000+) | Excellent | Best upscaling quality. Frame Gen available on RTX 4000+. |
| **FSR 2/3** | AMD FSR Plugin | ALL (cross-vendor) | Good | Works on all GPUs including consoles and Switch. |
| **PSSR** | PS5 SDK Plugin | PS5 Pro only | Excellent | Hardware-accelerated ML upscaling. PS5 Pro exclusive. |
| **XeSS** | Intel XeSS Plugin | PC (Arc, RTX, RX 6000+) | Very Good | Intel's ML upscaler. Works on Intel Arc + NVIDIA + AMD. |
| **NIS** | NVIDIA Plugin (or built-in) | ALL (cross-vendor) | Acceptable | Lightweight spatial upscaler. Good for Switch/low-end. |
| **TAAU** | Built-in UE5 | ALL | Legacy | Gen-4/Gen-5 TAA upsampling. Fallback for all platforms. |

### 3.2 Setting Up DLSS (PC High Profile)

1. Install the **NVIDIA DLSS** plugin from the UE Marketplace or NVIDIA Developer site
2. Enable in `Edit → Plugins → NVIDIA DLSS`
3. In `DA_RPP_PC_High`:
   - Add `DLSS` to `SupportedUpscalers`
   - Set default upscaler to `DLSS`
4. Console commands the manager sets when DLSS is active:
   ```
   r.NGX.DLSS.Enable 1
   r.NGX.DLSS.Quality {0=UltraPerf, 1=Perf, 2=Balanced, 3=Quality, 4=UltraQuality}
   r.NGX.DLSS.DilateMotionVectors 1
   r.NGX.DLSS.Reflections 1
   r.NGX.DLSS.WaterReflections 1
   ```

### 3.3 Setting Up FSR 2 (Cross-Platform Profile)

1. Install **AMD FidelityFX FSR 2** plugin
2. Enable in plugins
3. Console commands:
   ```
   r.FidelityFX.FSR2.Enabled 1
   r.FidelityFX.FSR2.QualityMode {0=Quality, 1=Balanced, 2=Performance, 3=UltraPerformance}
   r.FidelityFX.FI.Enabled 1              ← Frame Interpolation (FSR 3)
   ```

### 3.4 Upscaler Fallback Chain

`BPC_RenderPipelineManager.GetAvailableUpscalers()` implements a priority-ordered fallback:
```
Primary:    DLSS (if RTX GPU detected)
Fallback 1: TSR (always available)
Fallback 2: FSR (if plugin installed)
Fallback 3: NIS (cross-vendor lightweight)
Fallback 4: TAAU (always available, legacy)
```

---

## 4. Baked Lighting Fallback Configuration

When a platform/profile selects `Baked_Lightmass` as the GI method:

### 4.1 Level Preparation for Baked Lighting

1. Set all primary lights to **Static** (not Stationary, not Movable)
2. Build lighting: `Build → Build Lighting Only`
3. Ensure lightmap UVs exist on all static meshes
4. Configure `World Settings → Lightmass Settings`:
   - `Static Lighting Level Scale`: 1.0
   - `Num Indirect Lighting Bounces`: 3–10
   - `Indirect Lighting Quality`: 1.0–4.0
5. Place `Lightmass Importance Volumes` around playable areas

### 4.2 Reflection Setup for Baked Mode

When Lumen Reflections are off:
1. Place `Sphere Reflection Captures` throughout the level
2. Place `Box Reflection Captures` in interior rooms
3. Set capture resolution: 128–256 (performance) or 512 (quality)
4. Build reflections: `Build → Build Reflection Captures`

### 4.3 Console Variables for Baked Mode

```
r.DynamicGlobalIlluminationMethod 0     ← Disable Lumen
r.Lumen.Reflections.Allow 0             ← Disable Lumen reflections
r.Shadow.Virtual.Enable 0               ← Disable VSM, use CSM
r.SSR.Quality 2                         ← Enable screen-space reflections (fallback)
r.ReflectionMethod 2                    ← Use reflection captures
```

### 4.4 Mesh LOD Fallback

When Nanite is disabled:
```
r.Nanite 0                              ← Disable Nanite
r.StaticMeshLODDistanceScale 1.0        ← Maintain normal LOD distances
r.SkeletalMeshLODBias 0                 ← No LOD bias for skeletal meshes
```

Ensure all static meshes have:
- LODs generated (LOD0 = full detail, LOD1 = 50%, LOD2 = 25%, LOD3 = 10%)
- `LODForCollision` set appropriately
- `MinLOD` not locked to 0

---

## 5. Planar Capture System Compatibility

### How Pipeline Changes Affect Captures

| Pipeline Change | Impact on Planar Captures | Mitigation |
|----------------|--------------------------|------------|
| Lumen → Baked | Capture renders baked lighting (looks correct). No Lumen overhead → faster captures. | `SS_PlanarCaptureManager` increases `GlobalQualityCap` by 1 tier |
| Baked → Lumen | Capture now includes Lumen GI (if capture profile allows). Higher cost. | `SS_PlanarCaptureManager` caps `GlobalQualityCap` to `Medium` or lower |
| Nanite → LOD | Faster capture render. No Nanite rasterization cost. | `SS_PlanarCaptureManager` increases budget |
| LOD → Nanite | Slower capture. Nanite in SceneCapture2D adds cost. | `SS_PlanarCaptureManager` reduces `MaxRegisteredSurfaces` |
| CSM → VSM | Higher quality shadows in captures. Minor cost increase. | No budget change needed |
| Upscaler change | **No impact** — captures render at native quality tier resolution | — |

### Capture Budget Adjustment Logic (in SS_PlanarCaptureManager)

```cpp
void SS_PlanarCaptureManager::AdjustBudgetForPipeline(const SRenderPipelineConfig& Config)
{
    if (Config.GIMethod == ERenderPipelineMethod::Baked_Lightmass)
    {
        // Lumen is off — captures are cheaper, allow higher quality
        GlobalQualityCap = EPlanarCaptureQualityTier::High;
        MaxRegisteredSurfaces = DefaultMaxSurfaces * 1.5;
    }
    else if (Config.GIMethod == ERenderPipelineMethod::Lumen_GI)
    {
        // Lumen is on — captures are expensive
        GlobalQualityCap = EPlanarCaptureQualityTier::Medium;
        MaxRegisteredSurfaces = DefaultMaxSurfaces;
    }
    
    if (Config.MeshStrategy == EMeshStrategy::Nanite)
    {
        // Nanite in captures adds cost — reduce quality slightly
        if (GlobalQualityCap > EPlanarCaptureQualityTier::Medium)
            GlobalQualityCap = EPlanarCaptureQualityTier::Medium;
    }
}
```

### Per-Capture Lumen Toggle

In `BPC_PlanarCapture.ApplyQualityTier()`:

```cpp
// If global pipeline has Lumen OFF, force capture Lumen OFF
if (!RenderPipelineManager->IsLumenEnabled())
{
    QualityProfile.bEnableLumen = false;
}
```

---

## 6. Settings Menu Integration

### Video/Graphics Tab Layout (WBP_SettingsMenu enhancement)

```
┌────────────────────────────────────────────┐
│  VIDEO / GRAPHICS                          │
│                                            │
│  QUALITY PRESET    [Low ▼]                 │
│  ⚠ Changing to Low requires level reload   │
│                                            │
│  ──────── ADVANCED ────────                │
│  Resolution Scale  [========|===] 85%      │
│  Window Mode       [Fullscreen ▼]          │
│  VSync             [✓]                     │
│  Frame Rate Limit  [====|======] 60 FPS    │
│                                            │
│  Global Illumination  [Lumen ▼]  ⚠ reload  │
│  Shadow Method        [VSM ▼]     ⚠ reload │
│  Reflections          [Lumen ▼]   ⚠ reload │
│  Mesh Quality         [Nanite ▼]   ⚠ reload │
│                                            │
│  Upscaler            [DLSS ▼]              │
│  Upscaler Quality    [Quality ▼]           │
│                                            │
│  Texture Quality     [====|======] High    │
│  Post Process        [====|======] High    │
│  Shadows             [====|======] High    │
│  View Distance       [====|======] High    │
│  Foliage             [====|======] High    │
│  Anti-Aliasing       [====|======] High    │
│                                            │
│  Motion Blur         [✓]                   │
│  Depth of Field      [✓]                   │
│                                            │
│  Brightness          [======|====] 1.0     │
│  HDR                 [✓]  (if supported)    │
│                                            │
│  [Apply]   [Reset to Defaults]             │
└────────────────────────────────────────────┘
```

Features labeled `⚠ reload` require a level transition to take effect. The UI shows a warning banner when any of these are changed.

---

## 7. Platform Certification Notes

### Sony PlayStation TRC Requirements
- **Minimum FPS:** PS5 must maintain 60 FPS in performance mode, 30 FPS in quality mode
- **Resolution Floor:** PS5 must render at ≥ 1080p internal before upscaling
- **PS4:** Must maintain 30 FPS, ≥ 720p internal
- **PSSR:** Must be listed as available upscaler on PS5 Pro
- **HDR:** Must support HDR10 output if display supports it

### Microsoft Xbox Requirements
- **Xbox Series X:** Must support 60 FPS performance mode + 30 FPS quality mode
- **Xbox Series S:** May target 30 FPS in quality mode
- **VRR:** Should support Variable Refresh Rate on HDMI 2.1 displays
- **Quick Resume:** Must save render pipeline state for Quick Resume compatibility

### Nintendo Switch Requirements
- **Handheld:** Must maintain ≥ 30 FPS at native 720p panel
- **Docked:** Must maintain ≥ 30 FPS at ≥ 720p internal (upscaled to 1080p)
- **Dynamic Resolution:** Strongly recommended for maintaining frame rate
- **Memory:** VRAM budget must be ≤ ~3.25 GB (4 GB total, 0.75 GB reserved)

---

## 8. Testing Matrix

| Platform | Low Preset | Medium | High | Ultra | Validate |
|----------|-----------|--------|------|-------|----------|
| PS5 | Baked+CSM+LOD | Lumen+VSM+Nanite | Lumen+VSM+Nanite | Lumen+VSM+Nanite | Check 60 FPS at all tiers |
| PS4 | Baked+CSM+LOD | Baked+CSM+LOD | Baked+CSM+LOD | N/A | Check 30 FPS floor |
| Xbox Series X | Baked+CSM+LOD | Lumen+VSM+Nanite | Lumen+VSM+Nanite | Lumen+VSM+Nanite | Check VRR support |
| Xbox One | Baked+CSM+Proxy | Baked+CSM+LOD | Baked+CSM+LOD | N/A | Check 30 FPS floor |
| Switch (docked) | Baked+CSM+Proxy | Baked+CSM+LOD | Baked+CSM+LOD | N/A | Dynamic res active |
| Switch (handheld) | Baked+CSM+Proxy | Baked+CSM+LOD | N/A | N/A | 30 FPS at 720p |
| PC High (RTX 3080) | SSGI+CSM+LOD | Lumen+VSM+Nanite | Lumen+VSM+Nanite | Lumen+HWRT+Nanite | DLSS working |
| PC Low (GTX 1060) | Baked+CSM+Proxy | Baked+CSM+LOD | SSGI+CSM+LOD | N/A | FSR working |
| SteamDeck | Baked+CSM+LOD | SSGI+CSM+LOD | SSGI+CSM+LOD | N/A | FSR working, 40 FPS |

---

## 9. Quick Reference: Console Variables

| Setting | CVar | Values |
|---------|------|--------|
| **GI Method** | `r.DynamicGlobalIlluminationMethod` | 0=Off, 1=Lumen, 2=SSGI |
| **Lumen Reflections** | `r.Lumen.Reflections.Allow` | 0/1 |
| **Lumen Diffuse** | `r.Lumen.DiffuseIndirect.Allow` | 0/1 |
| **Shadow Method** | `r.Shadow.Virtual.Enable` | 0=CSM, 1=VSM |
| **Shadow Quality** | `sg.ShadowQuality` | 0=NONE, 1=LOW, 2=MED, 3=HIGH, 4=EPIC |
| **Reflections** | `r.ReflectionMethod` | 0=None, 1=Lumen, 2=SSR |
| **SSR Quality** | `r.SSR.Quality` | 0-4 |
| **Nanite** | `r.Nanite` | 0/1 |
| **TSR** | `r.TemporalAA.Upsampling` | 0/1 |
| **Screen %** | `r.ScreenPercentage` | 25–200 |
| **Texture Quality** | `sg.TextureQuality` | 0–3 |
| **Post Process** | `sg.PostProcessQuality` | 0–3 |
| **View Distance** | `sg.ViewDistanceQuality` | 0–3 |
| **Foliage** | `sg.FoliageQuality` | 0–3 |
| **AA Quality** | `sg.AntiAliasingQuality` | 0–3 |
| **Motion Blur** | `r.MotionBlurQuality` | 0=NONE, 2=MED, 4=EPIC |
| **DoF** | `r.DepthOfFieldQuality` | 0=NONE, 2=MED, 4=EPIC |
| **Volumetric Clouds** | `r.VolumetricCloud` | 0/1 |
| **Virtual Textures** | `r.VT.Enable` | 0/1 |
| **Ray Tracing** | `r.RayTracing` | 0/1 |
| **Texture Pool** | `r.Streaming.PoolSize` | MB value |
| **LOD Scale** | `r.StaticMeshLODDistanceScale` | 0.5–3.0 |
| **Foliage LOD** | `foliage.LODDistanceScale` | 0.5–3.0 |

---

*Platform Render Profiles Guide v1.0 — Part of the UE5 Modular Game Framework developer docs. Systems: BPC_RenderPipelineManager (149), DA_RenderPipelineProfile.*
