tower / commit
feat(interior): the collector gets a lit rim
README.md | 4 +++- decisions.md | 29 ++++++++++++++++++++++++ design.md | 9 ++++++++ docs/screenshots/desktop-exterior-true.png | Bin 506858 -> 506739 bytes docs/screenshots/desktop-exterior.png | Bin 332036 -> 332293 bytes docs/screenshots/desktop-interior-dawn.png | Bin 485508 -> 488654 bytes docs/screenshots/desktop-interior-night.png | Bin 276084 -> 275988 bytes docs/screenshots/desktop-interior-overhead.png | Bin 544165 -> 544184 bytes docs/screenshots/desktop-interior-suncap.png | Bin 383930 -> 397844 bytes docs/screenshots/desktop-interior.png | Bin 545739 -> 545739 bytes docs/screenshots/mobile-exterior.png | Bin 81564 -> 81707 bytes docs/screenshots/mobile-interior.png | Bin 172350 -> 172345 bytes docs/screenshots/overview.png | Bin 1152660 -> 1155305 bytes src/canon/constants.ts | 16 +++++++++++++ src/views/interior.ts | 30 ++++++++++++++++++++----- 15 files changed, 82 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4ff33ea..8f4d9a2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ is a kilometre of sealed hull: no windows along all 540 km, and no view of the E it orbits. Both end caps are windows, though — 100 km of glass each, and the only places in the world with a horizon that is not Tower. Nobody aboard can see the sun either: the 244 km collector sits between Tower and it, 79 times its diameter, so -the sun cap looks out at a black disc and the stars around it. +the sun cap looks out at a black disc and the stars around it — black except at its +edge, where the structure holding it flat catches the sun side-on and traces the +whole 244 km in a thin sun-coloured ring. Explore Tower from outside, pick a spot on the inner surface, and stand there — with the ground curving up on both sides and the far side of the world hanging 100 km diff --git a/decisions.md b/decisions.md index e19a1d5..29c1d02 100644 --- a/decisions.md +++ b/decisions.md @@ -1615,3 +1615,32 @@ scrubbing and ticking are the same operation. The readout names the distance to the line rather than just the hour, because the distance is the part you can act on: 27 km sunward is about two minutes' wait. + +## D-054 — The collector gets a lit rim + +Drawing the collector as pure black was right about its face and wrong about the +object. From inside the sun cap window at night you could not see it at all — only +that a piece of the sky was missing, which reads as a rendering hole rather than as +a 244 km structure. + +**The physics gives the rim for free.** The collector is backlit by definition: its +mirror face is pointed at the sun and away from Tower. Anything holding 46,938 km² +flat has structure standing proud of the mirror plane at the edge, and at the edge +the sun strikes that structure side-on. Add the scatter every real mirror throws at +grazing incidence and the boundary is a thin sun-coloured ring. That is simply how +backlit things look, and it is the one part of the collector that can be lit. + +**What it is not is sunlight past the edge**, and the distinction matters because the +first is a property of the object and the second would break canon. Tower sits wholly +inside the umbra — §1.3.0 — so the sun's disc is occulted from every point in the +world. Nobody sees a sliver of star; they see lit metal. + +Rendered as two exponentials: a tight core at the declared 4 km of edge structure, +and a wide dim skirt for the scatter around it. One alone reads as a drawn outline +rather than as light. The first attempt was three times too bright and its skirt +seven times too wide, which washed the whole disc gold instead of tracing it. + +**It does not scale with the beam.** The sun does not dim when Tower banks its own +lamp, so the rim is outside `uExposure`, like the stars. It does fade as the eye +adapts, but from a much higher floor than a star's — this is sunlit structure, and +it stays faintly visible at noon where a star cannot. diff --git a/design.md b/design.md index e4bae17..bdbbe05 100644 --- a/design.md +++ b/design.md @@ -105,6 +105,15 @@ infrared, and therefore black. It is the only object in Tower's sky that is neit Tower nor a star, and it never moves, because the collector flies in formation rather than spinning. D-050. +**Its edge is not black.** The face is a mirror pointed away, but the collector is +*backlit*, and the structure holding 46,938 km² flat stands proud of the mirror +plane at the rim, where the sun strikes it side-on. With the scatter any real mirror +throws at grazing incidence, the edge reads as a thin sun-coloured ring — so the +collector is a hole in the stars with a lit rim rather than an absence, which is how +anything backlit looks. **It is not sunlight leaking past the edge**: Tower is wholly +inside the umbra, so the sun's disc is hidden from every point in the world. The ring +is lit structure. D-054. + #### 1.3.1 The diffuser swarm The diffusers must be individually invisible, or the sky becomes a row of separate diff --git a/docs/screenshots/desktop-exterior-true.png b/docs/screenshots/desktop-exterior-true.png index 2615bcf..ef7e6af 100644 Binary files a/docs/screenshots/desktop-exterior-true.png and b/docs/screenshots/desktop-exterior-true.png differ diff --git a/docs/screenshots/desktop-exterior.png b/docs/screenshots/desktop-exterior.png index 3a19f4a..7810fb6 100644 Binary files a/docs/screenshots/desktop-exterior.png and b/docs/screenshots/desktop-exterior.png differ diff --git a/docs/screenshots/desktop-interior-dawn.png b/docs/screenshots/desktop-interior-dawn.png index 4dfd0e6..cee0a2a 100644 Binary files a/docs/screenshots/desktop-interior-dawn.png and b/docs/screenshots/desktop-interior-dawn.png differ diff --git a/docs/screenshots/desktop-interior-night.png b/docs/screenshots/desktop-interior-night.png index 24251b7..7e05589 100644 Binary files a/docs/screenshots/desktop-interior-night.png and b/docs/screenshots/desktop-interior-night.png differ diff --git a/docs/screenshots/desktop-interior-overhead.png b/docs/screenshots/desktop-interior-overhead.png index 7f169b7..e911380 100644 Binary files a/docs/screenshots/desktop-interior-overhead.png and b/docs/screenshots/desktop-interior-overhead.png differ diff --git a/docs/screenshots/desktop-interior-suncap.png b/docs/screenshots/desktop-interior-suncap.png index 2fce396..b17d8da 100644 Binary files a/docs/screenshots/desktop-interior-suncap.png and b/docs/screenshots/desktop-interior-suncap.png differ diff --git a/docs/screenshots/desktop-interior.png b/docs/screenshots/desktop-interior.png index 53b8fe1..9ab8ec9 100644 Binary files a/docs/screenshots/desktop-interior.png and b/docs/screenshots/desktop-interior.png differ diff --git a/docs/screenshots/mobile-exterior.png b/docs/screenshots/mobile-exterior.png index 0149785..2fa380c 100644 Binary files a/docs/screenshots/mobile-exterior.png and b/docs/screenshots/mobile-exterior.png differ diff --git a/docs/screenshots/mobile-interior.png b/docs/screenshots/mobile-interior.png index f1d92d7..ebdac10 100644 Binary files a/docs/screenshots/mobile-interior.png and b/docs/screenshots/mobile-interior.png differ diff --git a/docs/screenshots/overview.png b/docs/screenshots/overview.png index 3063fc3..bdeb741 100644 Binary files a/docs/screenshots/overview.png and b/docs/screenshots/overview.png differ diff --git a/src/canon/constants.ts b/src/canon/constants.ts index 1e1831a..e9e3ec9 100644 --- a/src/canon/constants.ts +++ b/src/canon/constants.ts @@ -81,6 +81,22 @@ export const COLLECTOR_STANDOFF_M = 320_000 */ export const COLLECTOR_ANGULAR_DIAMETER_RAD = 2 * Math.atan(COLLECTOR_DIAMETER_M / 2 / COLLECTOR_STANDOFF_M) +/** + * The sunlit rim. + * + * The collector's face is a mirror pointed away from Tower, so from inside it is a + * black disc — but it is a **backlit** black disc, and its edge is not. The array + * has to hold 46,938 km² flat, and the structure that does it stands proud of the + * mirror plane at the rim, where the sun strikes it side-on. Add the scatter any + * real mirror throws at grazing incidence and the edge reads as a thin sun-coloured + * ring: a crescent of lit structure with nothing behind it. 4 km on a 244 km disc. + * + * Note what it is *not*: sunlight leaking past the edge. Tower sits wholly inside + * the umbra (below), so the sun's disc is hidden from every point in the world. The + * ring is lit structure, not a sliver of star. D-054. + */ +export const COLLECTOR_RIM_M = 4000 + /** * Umbra radius at the sun cap. Tower's 51 km sits well inside it, which is what * makes the eclipse total rather than partial. diff --git a/src/views/interior.ts b/src/views/interior.ts index ad757dd..6650c5e 100644 --- a/src/views/interior.ts +++ b/src/views/interior.ts @@ -25,7 +25,7 @@ import { } from 'three' import { BEAM_RADIUS_M, BRIGHTNESS_FULL_W_M2, COLLECTOR_DIAMETER_M, COLLECTOR_STANDOFF_M, - DAY_LENGTH_S, DAY_SWEEP_FRACTION, BRIGHTNESS_NIGHT_W_M2, BRIGHTNESS_TEMPERATE_W_M2, + COLLECTOR_RIM_M, DAY_LENGTH_S, DAY_SWEEP_FRACTION, BRIGHTNESS_NIGHT_W_M2, BRIGHTNESS_TEMPERATE_W_M2, BRIGHTNESS_TWILIGHT_W_M2, G0, HULL_DEPTH_M, LENGTH_M, OMEGA_RAD_S, RADIUS_M, RAYLEIGH_FLOOR_PER_M, SPECIFIC_GAS_CONSTANT, TEMPERATURE_K, gravityAtHeight, @@ -50,6 +50,8 @@ const HULL_D = HULL_DEPTH_M / KM /** The collector, in km: 122 km of radius flying 320 km ahead of the sun cap. */ const COLLECTOR_R = COLLECTOR_DIAMETER_M / KM / 2 const COLLECTOR_Z = -COLLECTOR_STANDOFF_M / KM +/** Width of the sunlit edge structure, in km (D-054). */ +const COLLECTOR_RIM = COLLECTOR_RIM_M / KM /** * Rayleigh extinction per kilometre at floor density, per channel. @@ -389,11 +391,29 @@ void main() { vec3 dir = normalize(vWorld - uCam); vec3 sky = starField(dir); - // Cast on through the window to the collector's plane. Anything that lands on - // the disc is looking at its unlit back, which is as black as the sky is not. + /** + * Cast on through the window to the collector's plane. Anything landing on the + * disc sees its unlit back, which is as black as the sky is not — and the edge, + * which is the opposite: structure standing proud of the mirror plane with the + * sun striking it side-on (D-054). So the collector reads the way any backlit + * thing does, as a hole in the stars with a lit rim, rather than as an absence. + */ float t = (${COLLECTOR_Z.toFixed(1)} - vWorld.z) / min(dir.z, -1e-4); - vec2 hit = vWorld.xy + dir.xy * t; - if (t > 0.0 && dot(hit, hit) < ${(COLLECTOR_R * COLLECTOR_R).toFixed(1)}) sky = vec3(0.0); + if (t > 0.0) { + float r = length(vWorld.xy + dir.xy * t); + sky = mix(sky, vec3(0.0), step(r, ${COLLECTOR_R.toFixed(2)})); + // Tight core for the structure itself, and a wide dim skirt for the scatter + // around it. One exponential alone reads as a drawn outline rather than light. + float d = abs(r - ${COLLECTOR_R.toFixed(2)}); + float rim = exp(-d / ${COLLECTOR_RIM.toFixed(3)}) + + 0.10 * exp(-d / ${(COLLECTOR_RIM * 3).toFixed(3)}); + /** + * Not scaled by uExposure — the sun does not dim when Tower banks its beam. + * It does fade as the eye adapts, like the stars, but from a much higher floor: + * this is sunlit structure, and it stays visible at noon where a star does not. + */ + sky += vec3(1.0, 0.93, 0.78) * rim * (0.3 + 0.7 * uStarGain) * 0.42; + } vec3 face = mix(sky, mullion, frame.a); vec3 T = towerTransmittance(uCam, vWorld);