Nine agent skills for building Makepad/Rust games, ported from majidmanzarpour/threejs-game-skills. Same director-routed workflow and premium bar; runtime rewritten for this fork's game crates. - makepad-game-director entrypoint, routing, continuity, asset probe - makepad-gameplay-systems loop, movers vs rigid bodies, input, camera, netplay - makepad-aaa-graphics-builder lighting, shaders, budget, visual scorecard - makepad-game-ui-designer HUD, menus, touch and XR UI - makepad-debug-profiler defect bisection and profiling - makepad-qa-release verification ladder, evidence, packaging - makepad-3d-generator CC0 model search, casts, procedural geometry - makepad-image-generator texgen textures, palettes, sky, icons - makepad-audio-generator sample bank, mixer, material impacts, 3D audio Written against the real APIs in libs/game/*, libs/sim and apps/arcade: the game.* verb table, GameRenderer adaptive quality, the packed 6-float GameMeshVertex layout, script_mod! splash styling, makepad-test driving, and the BUDGETS.md numbers. No paid generation API is required - the CC0 library plus seeded makepad-game-gen replaces them. Includes install.sh (Codex/Claude), validate-skills.sh and a repo-aware probe_assets.sh; both scripts verified against this checkout.
79 lines
4.9 KiB
Markdown
79 lines
4.9 KiB
Markdown
# Lighting and materials
|
||
|
||
## The three-part model
|
||
|
||
**Key (sun).** `SunConfig`, `sun.rs`, `DrawGameSky`. Direction and colour. Elevation 15–25° gives long shadows and modelled forms; noon light flattens everything and is what an unconsidered scene looks like. Commit to a time of day.
|
||
|
||
**Ambient (hemispheric).** `sun_sky` above, `sun_ground` bounce below, interpolated by the normal's Y. Grey ambient is the flatness default. Colour the two ends: a warm key with cool sky ambient (or the reverse at sunset) is most of the distance between "rendered" and "lit".
|
||
|
||
**Fog.** `fog_color`, `fog_density`. Provides depth ordering and aerial perspective. **Fog colour must agree with the sky at the horizon**, or distant geometry sits on a visibly different backdrop.
|
||
|
||
All four are shader **uniforms**, not instance data (see `shader-cookbook.md`). `fog_density` is the one per-instance exception, because shadow draws switch it off individually.
|
||
|
||
## Consistency
|
||
|
||
`light_dir` must be identical across `draw_cube`, `draw_alpha`, `draw_terrain`, `draw_skinned`, `draw_models`. Set them together in one `script_mod!` block. Inconsistent light direction is the most-missed defect in this engine because each surface looks fine alone.
|
||
|
||
## Shadows
|
||
|
||
`shadow.rs`, `shadow_mesh.rs`, `set_shadow_budget(n)`, `shadow_budget()`. Shadow meshes use the same 6-float packed vertex.
|
||
|
||
Budget by importance:
|
||
|
||
1. The player — always.
|
||
2. Anything moving within the player's immediate area.
|
||
3. Tall objects whose silhouette defines the space.
|
||
4. Everything else — baked AO instead.
|
||
|
||
Shadowing everything kills the frame; shadowing nothing makes props float. Adaptive quality lowers the budget automatically under load — read `quality_reason()` before concluding your shadows "stopped working".
|
||
|
||
## Baked AO
|
||
|
||
`bake.rs`, `ao.rs`, `BakeSettings`, `bake_settings()` / `set_bake_settings()`, `dynamic_shade(pos)`.
|
||
|
||
**Contact darkening is the cheapest large upgrade to perceived quality.** It is specifically what stops props reading as stickers laid on the ground. Bake it for static props; use `dynamic_shade` for moving ones.
|
||
|
||
The `ao_render` dev example software-rasterises props so baked AO can be judged by eye without a `Cx` or the app — use it, because AO is a judgement call that a number does not settle. That example is why the crate carries a `jpeg-encoder` dev-dependency and no more.
|
||
|
||
## Materials without a PBR pipeline
|
||
|
||
There is no material graph here. Differentiation comes from four levers:
|
||
|
||
**Tint.** `ModelInstance::with_tint(vec4)`. Drive from `Palette` / `Spread` / `VarietyParams` in `makepad-game-assets`, or `find_palette` on the script route. Five palette-consistent tints across a crowd reads as authored; one tint reads as placeholder.
|
||
|
||
**Texture.** `with_texture(idx)` and `DrawGameTexture`. Generate tiling detail with `makepad-game-gen::texgen` when the library has nothing — procedural texture is free of download weight and is deterministic from a seed.
|
||
|
||
**Jitter.** Seeded, small: ±10% scale, full yaw rotation, slight position offset. This destroys the grid-stamped look at zero cost. Seeded, so it replicates.
|
||
|
||
**Cast variety.** For characters, use different members of ONE cast (`find_cast`) — same skeleton, so animation is shared, but the crowd is not clones.
|
||
|
||
## Palette
|
||
|
||
Three dominant + two accent. Rules that hold across genres:
|
||
|
||
- **Reserve accents for gameplay meaning.** If pickups are the only saturated orange in the game, the player learns orange without being told.
|
||
- **Separate by value, not only hue.** A screenshot converted to greyscale should still show foreground, midground, background as distinct bands. This is the test most scenes fail.
|
||
- **Desaturate with distance** toward the fog colour — aerial perspective, free depth.
|
||
- The CC0 library is shared, so out-of-the-box colours look like every other Kenney project. Tint discipline is what makes it yours.
|
||
|
||
## Skinned characters
|
||
|
||
`skin.rs` — `SkinnedModel`, `PoseBuffer`, `SkinnedBatch`, `SkinnedDraw`.
|
||
|
||
Skinning is **CPU-side**, so the whole skinned vertex buffer re-uploads every frame. That makes skinned characters the most expensive visual thing in the scene by bandwidth: the Knight is 3716 verts, 238 KB/frame unpacked, 89 KB packed. Consequences:
|
||
|
||
- Cap the number of on-screen skinned characters and prove the cap holds in the worst wave.
|
||
- Distant characters do not need full skinning — swap to a static or lower-rate pose.
|
||
- Share one cast per scene so one animation set serves everyone.
|
||
|
||
## Checklist before scoring
|
||
|
||
- [ ] Sun elevation committed and not noon
|
||
- [ ] `light_dir` identical across every draw type
|
||
- [ ] Sky ambient and ground bounce coloured, not grey
|
||
- [ ] Fog colour matches the sky at the horizon
|
||
- [ ] Player always casts a shadow
|
||
- [ ] Contact AO under every static prop
|
||
- [ ] No two adjacent props identical in tint, scale and yaw
|
||
- [ ] Greyscale screenshot still separates fore/mid/background
|
||
- [ ] Accent colour reserved for gameplay-relevant objects
|