**Foliage Distance** (`foliageDistance`, Advanced Graphics, 70..300 yd). The reference
draws ground clutter to a hardcoded 70 yd (`[0x867958]`) and we inherited it, so grass,
reeds and small bushes arrive at a fixed ring around the player — which is exactly where
the eye is drawn to them appearing. The row moves the ring; it changes nothing about what
grass looks like.
Measured on an Elwynn fence line (`fence-shadowline-day`, clutter density 2), p50 frame
time / main thread: 70 yd **3.25/3.26 ms**, 140 **3.32/3.24**, 200 **3.48/3.38**, 300
**3.69/3.42**, with the GPU flat throughout. Doubling it is free; past 140 it costs main
thread, which is the budget this client is short of. The registered default IS the
reference's own 70 and the row is in no preset ladder, so nothing moves until a player
asks it to.
It commits on Apply: `fade_far` is baked into the clutter material key, so a change drops
every built patch to be re-cut (338 meshes on one measured write) and a drag would do that
thirty times a second. `clutter::remesh_on_cutout_change` is now
`remesh_on_material_change` and watches both the alpha ref and the fade for that reason.
What it buys in a STILL is small — 70 -> 300 moves 0.6% of a frame, the far tufts being
sub-pixel — and that is the wrong instrument: the complaint is grass ARRIVING, which no
static capture can show.
**Light arrival fade** (`lighting::global_light`). No setting: a correction, not a taste.
A fixture enters the packed light table for several unrelated reasons — the portal walk
reaching its room, its WMO group streaming in, the camera crossing `INTERIOR_NEAR_ADMIT`
or `POINT_PACK_RADIUS`, the 255-entry capacity cut re-sorting — and every one of them was
a hard edge that switched a light on at full brightness between one frame and the next.
Measured in Ironforge by diffing the admitted set between static vantages: walking **3 yd
exchanged 2 of 172 admitted lights, and 10 yd exchanged 8** — about one arriving per yard,
which at a walk is several a second. The table ran 110-196 across five vantages and never
reached the cap, so this is admission churn and NOT capacity; the cap does bind
transiently during a world load (305 candidates seen once), which is why the boundary fade
below is kept.
Arrivals now ramp over 0.35 s, whichever rule admitted them. The scale lands on the
light's colour before the pack, so the GPU table, the CPU mirror, the fog lamps and the
froxel volume all follow from one write. Deliberately NOT symmetric: a departing fixture
still goes at once, because keeping it alive to dim means keeping its room claim alive
with it, and a stale claim gates a live light with a dead building's identity.
**Spell lights are exempt**, and that is the exemption that matters: a fireball's light
lives about as long as the ramp does, so ramping it would spend the whole effect at half
strength.
Beside it the capacity cut itself is softened — the last 24 admitted ranks scale toward
zero across the distance band they span — and nothing fades while the table fits, which is
what makes the control possible: with the ramp on against off, the Goldshire inn and the
Great Forge both settle BYTE-IDENTICAL.
Also recorded in docs/GRAPHICS.md: captures force `WOW_CLUTTER_DENSITY=0` for byte-stable
baselines, so a run that sets only `WOW_CLUTTER_FADE` measures a scene with no grass in it
and reports every horizon as free. Three rounds of this measurement were worthless before
the starved control caught it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn