# Lighting & Environment Setup Proper lighting is the difference between a map that looks professional and one that looks like a grey box. Tactical Shooter uses Godot's **LightmapGI** system for baked global illumination: light bounces are pre-calculated and stored in lightmaps, giving you realistic lighting at zero runtime cost. ## Lighting Architecture ``` DirectionalLight3D (sun) — main directional light, shadows └─ OmniLight3D (fill) — ambient fill lights, no shadow └─ LightmapGI — bakes all static lighting into textures └─ baked lightmaps (zero runtime cost) ``` ## 1. WorldEnvironment Every map needs a `WorldEnvironment` node. This controls: - **Sky** — Background appearance (skybox or solid colour) - **Ambient light** — Base light level for unlit surfaces - **Tonemapping** — Colour grading and exposure **Setup:** 1. The template already includes a `WorldEnvironment` node 2. If creating from scratch, add one via the scene tree → + button → `WorldEnvironment` 3. In the Inspector, assign an `Environment` resource (New Environment) 4. Configure: - **Background:** Sky (for outdoor) or Clear Color (for underground maps) - **Ambient Light:** Sky (mimics sky colour) or Color (custom ambient) - **Tonemap:** Reinhard or Filmic (prevents blown-out highlights) > The validator warns if WorldEnvironment is missing — add it early. ## 2. DirectionalLight3D (Sun) The main sun light. One per map. **Recommended settings:** | Property | Value | Reason | |----------|-------|--------| | `light_bake_mode` | Static (2) | Bakes into lightmap | | `shadow_enabled` | true | Required for competitive visibility | | `shadow_bias` | 0.1 | Prevents shadow acne on CSG | | `angular_distance` | 0.01 | Sharp sunlight (competitive visual clarity) | | `range` | 50–100 | Large enough to cover the map | **Positioning:** - Rotate the sun to create interesting shadows through windows/doorways - Avoid straight-down lighting (makes everything look flat) - A 45° angle works well for most maps ## 3. Fill Lights (OmniLight3D) Fill lights illuminate areas the sun doesn't reach (interiors, tunnels). **Rules:** - **Maximum 4 dynamic (non-baked) lights** — enforced by the validator - Fill lights should use `light_bake_mode = Static (2)` so they bake into the lightmap and don't count toward the dynamic budget - Use low intensity (0.3–0.5) for ambient fill **Performance tip:** Every omni/spot light with `shadow_enabled = true` is expensive. The validator warns on dynamic lights with shadows. Baked lights with shadows disabled are free — use them. ## 4. LightmapGI — Baked Global Illumination LightmapGI is the backbone of Tactical Shooter's lighting. It pre-computes light bouncing and stores the result as textures (lightmaps). ### Configuration | Property | Recommended | Notes | |----------|-------------|-------| | `quality` | 2 (High) | Higher = better GI, longer bake | | `bounces` | 3 | Minimum 2 for realistic indirect lighting | | `texel_scale` | 1.0–2.0 | Lower = higher res, longer bake | | `max_texture_size` | 1024 | Controls lightmap atlas size | | `use_denoiser` | true | Removes noise from baked result | | `environment_mode` | 0 (Baked Environment) | Uses WorldEnvironment for sky lighting | ### Baking To bake: select the `LightmapGI` node → click **Bake Lightmap** in the top toolbar (or `Ctrl+Shift+C`). **Baking checklist:** - [ ] All geometry is finalised (moving geometry after baking invalidates it) - [ ] All lights have correct bake mode (Static for baked, Dynamic for real-time) - [ ] CSG has `use_collision = true` (non-collidable CSG may not bake properly) - [ ] WorldEnvironment is configured with a sky or ambient colour - [ ] Save the scene before baking **Baking time:** Varies by map complexity. A small map (10×14 units) bakes in 30–60 seconds. A full competitive map (20×20) may take 5–10 minutes. ### After Baking - The LightmapGI node's `light_data` property will show a `LightmapGIData` resource - The validator checks for `light_data != null` to confirm the map is baked - Baked lightmaps are stored in the `.tscn` file as embedded resources - You can rebake at any time — it overwrites the previous lightmaps **Warning:** Opening an unbaked map on a server will default to unlit rendering. Always bake before packaging. ## 5. ReflectionProbe ReflectionProbes add specular reflections to shiny surfaces (metal, glass, water). - Place one `ReflectionProbe` near the `cubemap_origin` marker - Set `max_distance` to cover the visible area (10–30 units) - Enable `box_projection` for interior spaces (corrects reflection distortion) - Set `intensity` to 0.5–0.8 (realistic reflection strength) **Tip:** You need reflection probes even if your map has no mirrors — they make metal and plastic materials look correct. ## 6. Lighting Performance Budget | Metric | Limit | Enforced | |--------|-------|----------| | Dynamic (non-baked) lights | ≤ 4 | Validator (error) | | Total lights (baked + dynamic) | Unlimited | — | | LightmapGI bounces | ≥ 2 | Validator (warning) | | ReflectionProbes | ≥ 1 | Validator (warning) | | Lightmap max texture | ≤ 2048 | Project settings | If you exceed the dynamic light budget, set more lights to `light_bake_mode = Static (2)` — baked lights cost nothing at runtime. ## 7. Quick Start Checklist - [ ] WorldEnvironment with Environment resource assigned - [ ] DirectionalLight3D (sun) with shadows - [ ] 1–3 fill OmniLight3D with Static bake mode - [ ] LightmapGI with quality=2, bounces=3, texel_scale=1.0 - [ ] ReflectionProbe at cubemap origin - [ ] All geometry CSG has `use_collision = true` - [ ] Save scene → Bake LightmapGI (Ctrl+Shift+C) - [ ] Verify `light_data` is populated (not null) ## Troubleshooting | Problem | Likely Cause | Fix | |---------|-------------|-----| | Light leaks at corners | CSG gap < 0.01 units | Overlap CSG edges by 0.1 | | Baked lighting too dark | bounces too low | Set bounces ≥ 2 | | Lightmap seams visible | texel_scale too high | Lower texel_scale to 1.0 | | Shadow acne (striped shadows) | shadow_bias too low | Increase shadow_bias to 0.1 | | ReflectionProbe visible as sphere | probe_mode wrong | Set to Box or disable visibility | | Bake fails with error | Scene not saved | Save `.tscn` before baking | ## Next Steps - [Map Validation](04-validation.md) — run all checks on your scene - [Packaging & Shipping](05-packaging-and-shipping.md) — publish your map