Files
tactical-shooter/docs/mapmaking/03-lighting-and-env.md
T
shawn 34507f9043 docs: community mapmaking documentation (7-file SDK guide)
- docs/mapmaking/00-index.md — SDK overview with workflow diagram
- docs/mapmaking/01-getting-started.md — template setup & first map
- docs/mapmaking/02-building-geometry.md — CSG guide & prefab reference
- docs/mapmaking/03-lighting-and-env.md — LightmapGI baking guide
- docs/mapmaking/04-validation.md — validator CLI & CI/CD usage
- docs/mapmaking/05-packaging-and-shipping.md — .pck pipeline
- docs/mapmaking/06-faq-and-troubleshooting.md — 30+ common issues
- README.md — add mapmaking SDK link to features list
2026-07-01 18:47:06 -04:00

160 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` | 50100 | 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.30.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.02.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
3060 seconds. A full competitive map (20×20) may take 510 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 (1030 units)
- Enable `box_projection` for interior spaces (corrects reflection distortion)
- Set `intensity` to 0.50.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
- [ ] 13 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