# ADR 0013: Rendering tiers and post-process volumes

## Status

Accepted

## Context

All rendering configuration previously lived in `RenderingSettings` (`assets/project.ron`) and was applied globally to the single `ProjectRenderCamera`. Bevy 0.19 provides experimental Solari ray-traced GI and `FullscreenMaterial` for custom post passes, but no spatial post-process volumes. Game teams need local overrides (rooms, biomes) without forking Rust or duplicating levels.

## Decision

### GI tiers

| Mode | Behavior |
|------|----------|
| `GiMode::Auto` | Startup default: Solari deferred when RT GPU support is available; Forward PBR otherwise |
| `GiMode::Forward` | Bevy Forward PBR with HDR/TAA/SSAO/atmosphere/shadows |
| `GiMode::Solari` | Request Solari deferred; camera attaches Bevy Solari when RT support is available |

Runtime exposes `RenderingCapabilities { rt_supported, active_gi_path }` and a resolved `ActiveCameraRenderProfile` each frame.
ADR 0016 supersedes the ambiguous `active_gi_path` wording with explicit requested/effective GI fields and `EffectiveRenderStack` fallback reasons.

Bevy 0.19 Solari samples directional lights and emissive meshes, while point and spot lights require the normal PBR light pass that Solari cameras skip. The editor surfaces this limitation directly on point/spot `LightDesc` components and runtime-disables them while Solari is active; point/spot light authoring uses Forward PBR. Requested Solari tags project geometry for raytracing and switches camera plus opaque-renderer components to Solari as soon as RT support is available; render-world readiness counters report whether BLAS/TLAS/bind-group setup and compatible lights are actually ready.

### WYSIWYG

The unified viewport uses the same `ActiveCameraRenderProfile` resolution path for the editor fly camera and the possessed player camera, so authors see the blended stack in both modes.

### Post-process volumes

- **Shape:** axis-aligned box in entity local space (`half_extents` on `PostProcessVolumeDesc`).
- **Priority:** higher `priority` wins overlaps; equal priority → stable entity-id tie-break.
- **Edge blend:** weight fades from 1 at center to 0 at faces over `blend_distance`.
- **Override model:** each FX field is `None` = inherit project, `Some(v)` = override (prefab-style).
- **Custom FX:** one active fullscreen effect from the highest-priority contributing volume.
- **Non-goals v1:** baked GI, multi-shader stacks, per-mesh post FX.

### Crate boundaries

| Crate | Owns |
|-------|------|
| `settings` | `RenderingSettings`, `GiMode`, `ActiveCameraRenderProfile`, capabilities types, save/load |
| `shared` | `PostProcessVolumeDesc`, overrides, reflect registration, asset RON types |
| `game_hot` | Profile resolver, camera component application, Solari path, fullscreen effects |
| `editor` | All egui: Project Settings, Rendering panel, inspector, visualizers, commands |

Authoring is saved to disk; BRP mutates authoring only ([ADR 0009](0009-authoring-vs-hydrated.md)). No egui in `settings`.

## Consequences

- `camera_fx.rs` consumes `ActiveCameraRenderProfile`, not raw `RenderingSettings`.
- Editor Rendering panel explains GI fallback, overlapping volumes, and active contributors.
- Game teams keep global look in `project.ron`, local looks in volumes, reusable bundles in `assets/rendering_profiles/`, custom shaders in `assets/post_fx/`.
- Solari may break some debug draws and does not support point/spot lights in Bevy 0.19; `GiMode::Auto` remains the default startup path and the Rendering panel reports the limitation and render-scene readiness.
