Cloud port · measured field check

Are the cloud tops too bright?

A grounded check of the standalone Bonkahe→three.js cloud port (atmo=0), prompted by one observation: the sunlit cloud tops look bleeding bright. This page answers it with measured pixels, a math view, eight fly-through GIFs, and a neutral team read — no guessing.

The answer, measured: yes — the sunlit crowns clip to pure white, but it's vantage-specific. Looking down at the fully-lit tops, 11–20% of the frame pegs to white (byte 255). From the side, below, or distance the same clouds never exceed luminance ≈204 and don't blow at all.

Cause (team, high confidence): not the tonemap (that's a verified-faithful copy of Godot's filmic). The in-scatter light accumulation sums each step raw — no transmittance weighting, no normalization — so a fully-lit crown over-accumulates past the tonemap's white point (which sits at 1.0 with zero headroom) → clip.

1 · The math view — where it blows, in motion

Luminance measured in display space (sRGB, the value your eye reads). A pixel is “blown” when luminance ≥ 250/255. The clip-map repaints every blown pixel red, so you can watch the crowns flare exactly when the camera faces the lit tops — and stay clean otherwise.

Toggle each between the normal render and the clip-map. Red = clipped to white (form lost); grey = still holding detail.

Measured luminance by vantage (worst frame on each route, display sRGB, real GPU)

Vantagemean Lmax Lblown ≥250blowout

2 · The feel — eight fly-throughs

~12-second loops, real GPU, atmo=0, from all around the cloud field. Each carries a blind-critic read (neutral brief — they were not told to look for brightness).

3 · Atmosphere on vs off

The same deck view, atmospherics on vs off. Atmosphere halves the blowout (deck 11.5% → 4.8%) by mixing the crowns toward haze before tonemapping, so the brightest lobes keep a highlight rolloff instead of going to paper-white. It's a mitigation, not a fix — the crown still rides near the ceiling and re-clips under a hotter sun. atmo=0 (the version of record) is the brighter, more-blown one.

atmo off
atmo OFF · 11.5% blown

Crisper, but the lit tops clip.

atmo on
atmo ON · 4.8% blown

Milkier/lower-contrast, but the crowns hold form.

4 · Root cause & what could fix it

The team ran two math lanes (tonemap + lighting) and four blind visual lanes, neutral briefs, no poison. They converged:

Decisive next test (settles bug-vs-faithful, no guessing): read the linear HDR buffer at a known-blown crown texel (the port can output linear via the bloom pass) — is it ~1.3 or ≫2? — and check Bonkahe's SunshineCloudsCompute.glsl for whether his in-scatter weights by transmittance. That one fact picks the lever.

Options if we want to reduce it (your call — not picking one)

A · Fix the accumulation. Weight each in-scatter step by remaining transmittance (or divide by sample count) so the integral converges below 1. Highest leverage — if the source confirms ours diverges.
B · Add tonemap headroom. Raise the filmic white point above 1.0 (or lower the baked exposure_bias=2.0) so HDR ~1–1.5 lands below white and crowns roll off. Cheap, reversible, faithful-safe — but lifts/darkens the whole frame, not just crowns.
C · Soft-knee the in-scatter. Clamp/soft-knee the crown light (or lean harder on the working atmo path) so crown linear tops out ~1.0–1.3. Most surgical; risks flattening highlight variety if overdone.

5 · Honest limitations

The blind critics flagged more than brightness — recorded straight, not buried:

So brightness is one finding; edge-noise, the sun disc, and distant-mass are separate threads if we keep going.

Built from real-GPU captures (NVIDIA RTX 4070 Ti SUPER, D3D11). Luminance/clip measured per pixel in display sRGB (qa/tools/measure_brightness.py); GIFs assembled with ffmpeg two-pass palette. Evaluation by a 6-agent neutral team — two math lanes, four blind visual lanes, two-directional briefs, no poison. Findings are measurements and reasoned reads, not a beauty verdict; the CD's eye decides direction.

Cloud port: research_clouds/threejs-port/ · scope: diagnose, not fix.