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
This commit is contained in:
2026-07-01 18:46:10 -04:00
parent 159c554a86
commit 34507f9043
8 changed files with 1382 additions and 1 deletions
+159
View File
@@ -0,0 +1,159 @@
# 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