Parent epic: #482
Depends on: Slice C
Goal
Per-light shadow casting with sensible defaults and Ogre's existing shadow techniques. Keeps the no-shadow path free for users who don't want shadows.
Scope
- Per-light Cast Shadows toggle in the Light inspector.
- Per-light Receive Shadows toggle on materials/entities (existing Ogre concept — surface via the inspector for entities).
- Directional shadows: cascaded shadow maps via
Ogre::PSSMShadowCameraSetup. Configurable cascade count (2/3/4, default 3) and split lambda. One global config for now — per-light overrides are stretch.
- Spot shadows: standard shadow mapping. Resolution selectable (512/1024/2048).
- Point shadows: cubic shadow mapping (or omni-directional via 6 spots if the cube path is messy in our Ogre version).
- Global Shadow Quality preset: Off / Low / Medium / High — maps to shadow map resolution + filter quality + cascade count.
- Bias controls: depth bias + slope-scaled bias, exposed in an advanced expander per light (defaults that work for most scenes).
- New
ShadowController (src/ShadowController.{h,cpp}, QML_SINGLETON) holds global shadow params; per-light overrides on the LightManager side.
- Apply shadow technique lazily on first light enabling shadows; uninstall when no lights cast shadows (keeps no-shadow path zero-cost).
Acceptance Criteria
Effort
~7 days. Highest technical risk in the epic, mostly platform/driver quirks.
Parent epic: #482
Depends on: Slice C
Goal
Per-light shadow casting with sensible defaults and Ogre's existing shadow techniques. Keeps the no-shadow path free for users who don't want shadows.
Scope
Ogre::PSSMShadowCameraSetup. Configurable cascade count (2/3/4, default 3) and split lambda. One global config for now — per-light overrides are stretch.ShadowController(src/ShadowController.{h,cpp}, QML_SINGLETON) holds global shadow params; per-light overrides on theLightManagerside.Acceptance Criteria
scene.light.shadow_toggleper light.Effort
~7 days. Highest technical risk in the epic, mostly platform/driver quirks.