---
title: "Rivière unifiée et grimoire nocturne : ce que la nuit du 15 a livré"
subtitle: "De la courbe 2a à la scène 3D nocturne — rubans guidés, méandre vers l'horizon, paquets qui grossissent"
date: 2026-09-15
time: "08:27"
author: VFG / Rainbow Journey
publishedBy: idea
status: pub
tags: ["rainbowjourney", "devblog", "journal", "nuit", "riviere-unifiee", "monde-3d", "essai-2a"]
---

![Rivière unifiée et grimoire nocturne : ce que la nuit du 15 a livré](../images/covers/2026-09-15-essai-ui-ingame-2a-design-complet-paquets-riviere-panneaux.png)


Le journal du 15 à 05:40 clôturait la passe live et l'essai UI 2a sur `main`. La nuit suivante ouvre un chantier différent : **unifier** la rivière 2D et la scène 3D, poser un **grimoire nocturne** (ciel, aurores, glyphes, lucioles), et répondre au retour FG sur le flux visuel — méandre vers l'horizon, rayons alignés, sacs qui grossissent avec la quantité.

Branche : `feat/riviere-unifiee-nuit-neon`, depuis `main` `467416b`. Agent : Claude Code (claude-opus-5).

## Commits

| Commit | Contenu |
| --- | --- |
| `bf0308c` | Plan, objectifs, décision et notices, commités avant tout code |
| `40ac14d` | `RiverField` : déprojection de la courbe 2a (eau + cascade), tests |
| `e971b0a` | Rivière 3D unifiée, rubans guidés, orbes, arrivées, ciel, glyphes, vallée, défauts nuit, passe HUD |

## Ce qui est livré (itération 1)

- **O1 — Courbe unique** : `src/world/riverPath3d.ts` reconstruit chaque couloir en monde à partir de `sampleRiverPath`. Les tests vérifient une reprojection sous 0,5 px en 1280×800 et 1920×1080 avec sway. La nappe colore ses veines en espace écran (`gl_FragCoord`) avec la même courbe analytique.
- **O2 — Rubans et orbes** : les rubans de notes lisent une texture de couloir. La tête avance au rythme de `climbDuration`, la queue part au relâchement. Les orbes suivent `runtime.climbers` ; une gerbe apparaît à la disparition d'un climber arrivé. Le compteur du paquet reste incrémenté par `settle` dans le runtime.
- **O3 — Fin du trapèze sur les couloirs** : le trapèze `--piano-warp` ne s'applique plus aux couloirs. Les aides de trapèze restent pour le piano DOM historique et `layout.test.ts`.
- **O4 — Nuit par défaut** : `sky #040a0a`, `water #0a3b3d`, bloom 0,7, seuil 0,6, brume 0,009, filaments 1. Ajouts : dôme d'étoiles avec lune, aurores teintées par les deux couloirs les plus actifs, pluie de glyphes runiques derrière la cascade, terrain à lignes de niveau, pins et cristaux émissifs, lucioles.
- **O5 — HUD grimoire** : calque d'atmosphère (grille, vignette, scanlines), ondes sur les médaillons tenus, surface liquide des paquets et rune à l'arrivée, entrée holographique des cartes, crochets de panneaux, balayage de la topbar. Le compas pastel `.world-status` est masqué.
- **Trace** : `?riviere-trace` (ou `debugcase`) affiche un trait de 1 px par couloir au-dessus de la 3D.

## Itération 2 — retour FG

Demande : aligner les rayons sur le flux de la rivière vers l'horizon, courber la rivière pour qu'elle se voie mieux, faire grossir les sacs selon la quantité.

- `src/journey/riverGeometry.ts` : nouvelle courbe en trois tronçons (pied vertical, méandre vers le col d'horizon, éventail vers le paquet), `riverThroatX` et `riverLaneCompression`. Les shaders reprennent la même courbe analytique à partir des constantes TypeScript.
- `src/world/riverPath3d.ts` : conversion cadre → écran ancrée sur le haut réel des couloirs, l'horizon et l'ancre des paquets. Le vecteur latéral et la nappe sont resserrés au col.
- `src/journey/pouchGrowth.ts` : croissance logarithmique (largeur ≤ 1,2, hauteur ≤ 1,55) appliquée par variables CSS, avec une transition élastique. L'ancre de la rivière reste sur la hauteur de base.
- Lumière nocturne atténuée (le terrain proche est désormais visible).

## Contrôles exécutés

Sur `e971b0a` et l'itération 2 :

- `node node_modules/typescript/bin/tsc -b --force` : OK.
- `npm run lint` : OK.
- Vitest : 33 fichiers, 251 tests réussis (itération 2).
- `vite build` : OK (avertissement de taille de chunk préexistant).
- Banc `src/perfBench.test.ts` (proxy CPU, machine locale) : `updateTrailInstances` à 1,55 ms/itération incluant `RiverField.update` ; `updateBridgeKeys` à 0,04 ms/itération. Aucune comparaison avec l'ancien chemin : le périmètre mesuré a changé.
- Rendu Browser pane (Vite isolé port 5186) : 1280×800, 1920×1080, mobile 375×812 avec `?riviere-trace` et la démo. Tracé 1 px coïncide avec rubans et veines ; paquets s'incrémentent ; aucune erreur console après rechargement. FPS topbar 58 dans le pane : observation, pas mesure de perf.
- Captures Chromium headless (SwiftShader, itération 2) : tracé coïncide, paquets grossissent, aucune erreur console. FPS headless (2 à 8) = rendu logiciel, pas mesure.
- Playwright (port 5187) : 5 réussis, 8 échoués — échecs attendent des éléments retirés par l'essai 2a avant ce chantier (titre `Do majeure`, 25 `.key`, bouton `Piano et fumee`). Probablement préexistants sur `main` ; non vérifié par exécution sur `main`.

## Non fait / écarts

- `docs:check` : 44 erreurs préexistantes (catalogue images, zone bundle design) ; aucune nouvelle erreur attribuable à ce chantier au moment du commit plan.
- Aucune mesure GPU, validation DP1 ou calibration perceptuelle.
- E2E piano DOM historiques à réécrire pour les couloirs 2a (zone outillage).
- `effects.riverWidth` règle maintenant la largeur minimale de la vallée ; libellé éditeur inchangé.

## Prochaine action

1. FG juge le rendu en jeu avec le DP1 (lisibilité rubans sur cascade, intensité aurores et bloom).
2. Ajuster au besoin `src/world/tuning.ts` (`cascadeFrameY`, `orbPx`, `sealPx`, `ribbonPxPerUnit`) et intensités shaders.
3. Réécrire les E2E piano DOM pour les couloirs 2a, puis décider de l'intégration de la branche.

---

*Sources : `docs/plans/riviere-unifiee-nuit-neon/handoffs/2026-09-15-riviere-unifiee-handoff.md`, `docs/plans/riviere-unifiee-nuit-neon/PLAN.md`, `docs/decisions/2026-09-15-riviere-2a-maitresse.md`. Miroir local : `RainbowPiano/docs/devblog/`.*