A GPUParticles3D emitter in the dive site re-centres on the active camera every frame and restarts after a jump, so flakes keep their own slow sink and drift while the submarine moves through them. Soft additive billboard discs dimmed by the water column and faded over their life replace the sphere volume that was attached to the submarine and turned with it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
24 KiB
Proposition — terrain du site de la zone I : « Banc du Vigilant »
Statut : validé par Olivier le 2026-10-06 (plan de masse, objet secondaire à 62 m, pipeline par script de cuisson, nom « Banc du Vigilant » conservé). Sert de spécification de référence pour l'implémentation.
Recuisson du 2026-10-06 (demande d'Olivier) : la rupture et le tombant
sont stratifiés en gradins de 4 m (Strata, bande z ≥ 118 m, hors Saignée et
amers) ; le plateau reçoit un relief de fond à trois échelles (250–15 m ± 2,2 m,
80–10 m ± 1,2 m, 20–5 m ± 0,6 m) et la roche un bruit de pente (SlopeRoughness).
L'objet secondaire est reculé de 3 m (63 m), le premier débris de 2 m, et le
point de la route sûre au-dessus de la lèvre de la Saignée remonté à 24 m pour
garder 3 m de dégagement. Voir docs/briefs/terrain-varied-landforms.md §4.3 bis.
Rédigée le 2026-10-06 à partir de docs/GAME_DESIGN_PLAN.md,
docs/VERTICAL_SLICE_TECHNICAL_PLAN.md, docs/POC_B_TECHNICAL_BASELINE.md,
des ADR 0004, 0006, 0008, 0010 et du code sous game/world/. Rien n'a été
exécuté ; aucun fichier de jeu n'est modifié par ce brief.
1. Objectif
Donner au premier site de plongée (navire de prospection, zone I, 35 m) un terrain statique, crédible et porteur de gameplay : le relief doit cacher l'épave, se lire au sonar, offrir une route sûre et une route risquée, et rendre la recherche intéressante sans marqueur. C'est la pièce « terrain graybox » de la tranche 3 du plan technique.
Terminé quand :
- un joueur sans aide trouve l'accès à l'épave cible en 5 à 10 minutes après l'arrivée dans la zone (critère §5 du plan technique) ;
- les deux routes existent, se distinguent au sonar et se justifient par les ressources (profondeur, batterie, collisions) ;
- le sonar renvoie roche, sable et métal selon la cellule touchée, pas un seul matériau pour tout le fond ;
- l'environnement de test du véhicule utilise la même implémentation de terrain que le site (une seule implémentation par concept) ;
bash scripts/quality_gate.shpasse.
2. Ce qui existe et ce qui contraint
| Élément | État | Conséquence pour le terrain |
|---|---|---|
game/world/sites/vehicle_test_environment.gd |
heightmap analytique 61×69, 180×200 m, -40 à -78 m, HeightMapShape3D |
graybox de test ; devient un client du nouvel acteur terrain |
game/world/sonar/reference_bathymetry_acquisition.gd |
rayons verticaux, lit sonar_material / sonar_reflectivity sur le collider |
le sonar suit tout terrain qui a une collision ; matériau par corps, pas par cellule |
| ADR 0010 | surface unique en V1 | pas de grotte, tunnel ni surplomb porteur d'information |
| Plan technique §3 | terrain conçu à la main, route sûre + route risquée | pas de génération procédurale à l'exécution |
| Plan technique §13 | chargement du site ≤ 3 s, 60 FPS 1080p | taille et découpage du maillage bornés |
| ADR 0010 | les limites de zone ne sont pas un relief à interpréter | la frontière jouable est une règle applicative, pas un mur de terrain |
| GDP §18 | low-poly atmosphérique, textures simples, identité par lumière et brouillard | réalisme = formes et lumière crédibles, pas photoréalisme |
| GDP §4.1 | coque I certifiée 60 m ; 100–115 % = dégâts croissants | une route ou un objet entre 60 et 69 m est un risque lisible, pas une mort |
| GDP §7.1 | zone d'écho de surface : 150 m, puis 75 m, minimum 50 m | le joueur arrive à ≤ 75 m de l'épave ; la portée sonar est 95 m |
| GDP §13.2 | une cible récente, deux leurres légers inscrits au registre | trois sites d'épave sur un seul terrain |
Point à vérifier avant de bâtir dessus (non vérifié à l'exécution) : dans
vehicle_test_environment.gd, le maillage visuel place la ligne 0 à z = +28
(proche) alors que HeightMapShape3D place la ligne 0 au z local le plus
négatif. Si c'est confirmé, la collision actuelle est le terrain visuel
retourné avant/arrière, et le sonar scanne la collision, pas le maillage. Les
tests d'intégration ne le détecteraient pas (ils comptent des échantillons,
pas une forme). Le nouvel acteur terrain doit avoir un test qui compare
hauteur visuelle et hauteur de collision en quelques points. Résolu : l'acteur
terrain compare collision et champ de hauteur dans
tests/integration/run_site_terrain_integration.gd.
3. Partis pris de réalisme
Le site est une plate-forme carbonatée de bordure de plateau caraïbe, l'environnement réel le plus courant à 25–45 m dans l'arc antillais :
- Plateau à 22–32 m : dalle de calcaire corallien recouverte de sable biogène, patch reefs isolés, rides de sable orientées par la houle.
- Système d'éperons et sillons (« spur and groove ») sur la bordure externe : crêtes rocheuses parallèles séparées de couloirs de sable de 8 à 20 m de large, descendant vers la rupture de pente. C'est la forme la plus lisible au sonar et la plus naturelle pour créer des couloirs de navigation.
- Rupture de pente à 42–48 m puis tombant jusqu'à 85 m, avec un cône d'éboulis au pied des sillons.
- Sédimentation : un navire échoué sur une pente de sable biogène s'enfonce et se recouvre partiellement en quelques mois ; les objets lourds glissent vers le bas de la pente. Les deux phénomènes servent le gameplay.
Ce qui reste hors réalisme volontairement : pas de corail animé, pas de végétation dense, pas de courant (V0.5), pas de houle. Les formes, la lumière décroissante avec la profondeur, le brouillard et les particules portent la crédibilité, conformément à la direction artistique.
4. Le site
4.1 Dimensions
| Donnée | Valeur proposée |
|---|---|
| Zone jouable | 600 × 600 m |
| Terrain physique | 768 × 768 m (marge de 84 m de chaque côté, noyée dans le brouillard) |
| Champ de hauteur | 513 × 513 cellules, 1,5 m par cellule, élévations float32 (SiteTerrainData) |
| Profondeur min / max du terrain | 20 m / 88 m |
| Profondeur d'écrasement coque I | hors terrain : le fond ne tue jamais par lui-même |
| Mouillage du navire | centre nord du plateau, 25 m de fond |
| Point de départ du sous-marin | sous le navire, 10 m de profondeur |
Les distances sont dimensionnées pour l'autonomie Standard (environ 1,2 km, 16 minutes d'oxygène) : aucune épave à plus de 320 m du mouillage, aucune paire d'épaves à plus de 260 m l'une de l'autre.
4.2 Plan de masse (nord en haut, navire au centre nord)
N
+---------------------------+ 20 m plateau clair, sable + patch reefs
| [Navire] |
| Rides . . | 26 m [B] leurre 1 : voilier de plaisance
| ~ ~ ~ [B] | posé à plat sur le sable, visible
| ~ ~ ~ ~ |
| les Deux ^^ l'Échine | 28 m crête longue nord-sud = fil d'Ariane
| Frères ^^ |||| |
| |||| |
| la Saignée |||| | 40 m [C] leurre 2 : caboteur acier dans
| \\\\\\ || [C] | un patch reef, échos roche + métal
| \\\\\\ || |
| \\\\\\ ====== | 45 m rupture de pente (ligne continue)
| \\\\\ [A] | 35 m [A] CIBLE : navire de prospection
| ----- .. . | dans un sillon, poupe sur la rupture
| tombant . . . | 50-64 traîne de débris descendant la pente
| ======== . | 62 m objet secondaire, légèrement
| 85 m | sous la profondeur certifiée
+---------------------------+
S
Noms de travail : l'Échine (crête de 6 m de haut), les Deux Frères (deux pitons jumeaux de 6 m de haut), les Rides (champ de rides de sable), la Saignée (sillon principal), le Tombant.
4.3 Les trois épaves et leur terrain
[A] Cible — navire de prospection (35 m). Couché dans le sillon de la Saignée, à 15 m de la rupture de pente. Coque enfoncée d'un tiers dans le sable (GDP §7.6, « coque enterrée dans le sédiment ») : au sonar, elle se lit comme une bosse allongée métallique dans un couloir, pas comme une silhouette évidente. La poupe dépasse au-dessus de la rupture ; le portique, un conteneur et une partie du gréement ont glissé en contrebas et forment une traîne de débris de 50 à 64 m le long du tombant. La traîne est un fil conducteur : un joueur qui descend trop tôt sur le tombant la rencontre et peut la remonter jusqu'à la coque. Caché par : la bosse de l'Échine à l'est, la profondeur du sillon, le sédiment.
[B] Leurre 1 — voilier de plaisance (26 m). Posé à plat sur le sable, en plein plateau, au bord des Rides. Facile à trouver, visible de loin. Bois et résine : écho faible, aucun métal massif. Il apprend au joueur à lire une silhouette et une matière au sonar. Contradiction découvrable : pas de portique, un seul mât, taille moitié moindre.
[C] Leurre 2 — caboteur en acier (40 m). Encastré dans un patch reef sur le flanc est de l'Échine. Même ordre de taille que la cible, même matériau : le vrai piège. Les échos roche et métal se mêlent ; il faut contourner et scanner deux fois pour isoler le contact. Contradictions : immatriculation différente, deux hélices au lieu d'une, pas de portique, avarie qui ne correspond pas au rapport.
4.4 Les deux routes vers la cible
Route sûre — par l'Échine (≈ 450 m, 26–32 m). Depuis le navire, suivre la crête longue vers le sud. Elle est lumineuse, large, sans obstacle, et se lit d'un seul scan. Elle mène au bord du plateau au-dessus de la Saignée : il faut ensuite descendre dans le sillon par son extrémité nord, à faible pente. Coût : temps et batterie. Récompense : zéro dégât, retour facile à estimer.
Route risquée — par la Saignée (≈ 340 m, 36–48 m). Un sillon de 12 à 18 m de large, aux parois de 8 à 10 m, qui coupe le plateau en diagonale et débouche directement sur la proue de la cible. Sombre (les projecteurs deviennent nécessaires), étroit (collisions), en pente (la batterie de remontée compte). Au sonar : une dépression continue, lisible comme une « ouverture possible » (GDP §7.2, point 4). Aucune paroi ne surplombe, donc compatible ADR 0010. Récompense : trajet plus court et direct sur la proue.
Le tombant — la tentation (50–64 m). Pas une route : une pente qui descend sous la rupture. L'objet secondaire (1 unité, ~200 €) repose à 62 m, dans la zone 100–107 % de la profondeur certifiée : craquements, dégâts lents, alerte claire. Le joueur voit la traîne de débris descendre et doit décider de s'arrêter. C'est le « site légèrement sous la profondeur certifiée » de GDP §7.6 appliqué à un objet optionnel, jamais à la cible.
4.5 Repères pour naviguer sans GPS
Le joueur n'a ni carte locale ni marqueur. Le terrain doit donc fournir des amers reconnaissables au sonar à 95 m :
| Amer | Forme sonar | Rôle |
|---|---|---|
| l'Échine | crête longue de 6 m de haut, orientée nord-sud | fil d'Ariane entre le navire et la cible |
| les Deux Frères | deux pitons jumeaux, 6 m de haut, 20 m d'écart | repère ouest unique, sert à se recaler |
| les Rides | ondulations régulières de 1 m | signe « plateau nord, navire proche » |
| la Saignée | sillon rectiligne, bords nets | entrée de la route risquée |
| la rupture de pente | ligne continue de rupture | « ne pas dépasser » et limite sud |
Chaque amer est unique sur le site : aucune forme n'est répétée ailleurs, pour que la reconnaissance ne trompe pas.
5. Ce que le terrain apporte au gameplay
- Chercher avant de récupérer (pilier GDP §1.4) : la cible n'est ni la plus visible [B] ni la plus « métallique » [C] ; elle est la plus cachée. L'écho de surface amène à ≤ 75 m, le sillon et le sédiment font le reste.
- Lecture du sonar comme compétence : rides = plateau, crête = route, dépression = passage, bosse dans un couloir = chose enfouie. Le site enseigne un vocabulaire que les sites suivants réutiliseront.
- Risque prévisible : chaque danger s'annonce avant de coûter. Le sillon est visiblement étroit, la pente visiblement longue, l'objet à 62 m visiblement sous la ligne de rupture.
- Décision de retour : la route risquée à l'aller et l'Échine au retour est le plan « malin » ; le terrain rend ce raisonnement possible.
- Enquête matérielle : la traîne de débris raconte le naufrage (impact sur la rupture, glissement, enfouissement) et concorde avec le rapport de la société, ce que les leurres ne font pas.
- Rejouabilité : revenir au site après identification (GDP §8, « repère local ») pour récupérer l'objet secondaire est une mini-expédition avec un seul but : gérer la profondeur.
6. Sonar et matériaux par cellule
Aujourd'hui le matériau sonar est une meta par corps. Le site a besoin de roche, sable et métal selon l'endroit touché :
- un champ d'octets de matériaux (un octet par cellule : roche ou sable,
déduit de la pente à la cuisson puis corrigé par des
MaterialPatchnommés dans la recette) est stocké dans leSiteTerrainDataà côté des élévations ; - l'acteur terrain expose
sonar_material_at(world_position)etsonar_reflectivity_at(world_position); l'acquisition les appelle quand le collider les possède, sinon lit la meta comme aujourd'hui ; - réflectivités de départ : roche 0,72 (valeur actuelle), sable 0,45, métal 1,0. Les valeurs vivent dans la définition de site, pas dans le code.
Les épaves restent des corps distincts avec leur propre meta ; le clustering de contacts existant les sépare du fond.
7. Rendu
- Un seul matériau terrain, shader Forward+ : mélange triplanaire sable / roche piloté par la pente (sable sous 25°, roche au-dessus de 40°, fondu entre), normal map de rides sur le sable, teinte assombrie avec la profondeur pour suivre la palette GDP §18.2 (vert clair à 25 m, bleu froid à 45 m, indigo au pied du tombant).
- Maillage découpé en 64 tuiles de 96 × 96 m (64 × 64 cellules), avec
visibility_rangepour ne dessiner que les tuiles dans le brouillard utile ; une seuleHeightMapShape3Dpour la collision. Les tuiles qui contiennent une pente de plus de 35° sont rendues à deux sommets par cellule sur la surface bicubique (Catmull-Rom, qui passe par chaque nœud du champ, bornée entre nœuds pour ne jamais dépasser une marche) : les facettes de la grille disparaissent sur les parois, la collision reste sur la grille et coïncide avec le rendu aux nœuds. L'échantillonnage des tuiles est pur et s'exécute en parallèle (WorkerThreadPool), les maillages sont assemblés ensuite sur le thread principal. - Props low-poly posés à la main, en nombre borné : blocs d'éboulis au pied du tombant, têtes de corail sur les patch reefs, rien d'animé.
- Flore et encroûtantes (2026-10-07, demande d'Olivier) :
SeabedFloraActorsème, depuis le champ de hauteur et une graine dérivée de l'identifiant du site, des touffes d'herbier sur le sable plat de la bande éclairée (pleines à 20 m, absentes à 36 m, en prairies par bruit) et des gorgones sur la roche de 15 à 60 m, cap croisé sur la houle ; uneMultiMeshpar tuile et par espèce, maillages et textures à découpe alpha procéduraux (SeabedFloraAssets), ondulation en vertex shader, aucune collision ni présence sonar. Le shader roche ajoute gazon algal sur les faces éclairées, croûtes corallines par plaques et éponges encroûtantes à l'ombre, le tout s'éteignant entre 40 et 75 m. L'optique de la colonne d'eau est partagée parwater_light.gdshaderinc. Têtes de corail en volume (même jour) : trois dômes bosselés procéduraux (massif, cerveau à crêtes, lobé) à base plate, semés sur la roche douce (< 30°) de 12 à 40 m en patch reefs par bruit, uneMultiMeshpar tuile et par variante, shader opaqueseabed_coral.gdshader(couleur de sommet × teinte d'instance, marbrure, même colonne d'eau). - Particules en suspension (même jour) :
MarineSnow, émetteurGPUParticles3Den espace monde recentré sur la caméra active, boîte de 44 × 28 × 44 m, 1 800 flocons de 3 à 9 cm qui coulent à 3,5 cm/s avec turbulence, disques doux additifs en billboard, atténués par la colonne d'eau et fondus en début et fin de vie. Remplace le volume de sphères attaché au sous-marin (qui tournait avec lui). - Brouillard, lumière directionnelle et particules de la scène de test actuelle sont conservés et réglés par site.
- Passe lumière du 2026-10-06 (
dive_site.tscn) : l'ambiance vient d'un ciel procédural sous-marin (haut turquoise, horizon aligné sur le brouillard, bas presque noir), ce qui éclaire les faces à l'ombre ; la source d'ambiance « ciel » était déclarée sans ciel, d'où les ombres noires. Directionnelle plus haute et plus forte (62°, 1,35) avec ombres douces à 70 % d'opacité, SSAO pour l'occlusion à l'échelle du maillage, tonemap filmique, perspective aérienne et albédo du brouillard volumétrique teintés. - Lumière par profondeur (même jour) : le shader atténue la lumière du jour
par Beer-Lambert spectral (absorption par canal 0,11 / 0,04 / 0,032 par
mètre, normalisée à 24 m) ; la partie scalaire réduit le soleil (fonction
light(), directionnelle seulement) et l'ambiance ciel (AO), la partie chromatique teinte l'albédo. Les projecteurs du sous-marin ne sont pas atténués. Plancher à 5 % pour que le pied du tombant reste lisible. Palette GDP §18.2 obtenue de fait : vert-bleu à 24 m, bleu froid à 45 m, indigo au pied du tombant ; ciel, brouillard et soleil (0,9, ombres 45 %) refroidis. - Brouillard par profondeur : un
FogVolume(WaterColumn, 1,8 km × 260 m) porte un shaderfog(water_column_fog.gdshader) dont l'albédo suit la même transmittance spectrale que le fond et dont la densité croît lentement sous 24 m ; la densité volumétrique globale passe à 0, la portée volumétrique à 128 m, le brouillard de distance (couleur fixe, 0,0045) ne couvre que l'au-delà. Tuilage du sable cassé par une déformation de domaine lente (37 m), une seconde échelle de rides (11,3 m) et une extinction des rides entre 40 et 60 m de fond.
État du 2026-10-06 (demande d'Olivier) : le shader mélange sable et roche
par la pente à partir de 20° (sable sous 20°, roche au-dessus de 40°, fondu
entre ; le matériau sonar bascule à 20°). La roche est en normal map
triplanaire monde (deux échelles, 7 m et 1,7 m) ; le sable porte une normal
map de rides orientée par la houle sur le plan xz ; une carte de grain sert
d'occlusion de détail et de marbrure d'albédo. Les trois cartes sont
procédurales, sans asset, construites par SeabedDetailTextures (bruit seedé,
sans couture, mipmaps) dans la couche monde. Le maillage n'a pas de tangentes :
les normales perturbées sont calculées en espace monde dans le shader.
8. Architecture proposée
| Couche | Élément | Responsabilité |
|---|---|---|
game/domain/sites/ |
DiveSiteDefinition (Resource typée) |
identifiant, nom affiché, SiteTerrainData, limites jouables, position et cap de départ, placements (épaves, leurres, objet secondaire, débris), routes de contrôle |
game/domain/sites/ |
TerrainHeightField (RefCounted pur) |
lecture de hauteur et de matériau à une position, conversion monde ↔ cellule, bornes ; testable sans scène |
game/application/sites/ |
PlayableBoundsRule |
« hors zone » comme résultat typé depuis la télémétrie ; émet un avertissement, jamais un mur |
game/world/sites/ |
BathymetricTerrainActor |
construit tuiles, collision et matériau depuis la définition ; expose matériau sonar par position |
game/world/sites/ |
dive_site.tscn (générique, configurée par une DiveSiteDefinition) |
scène de site : terrain, environnement, points d'injection pour épaves et navire |
game/composition/ |
câblage | charge la définition, instancie le site, injecte la règle de bornes |
content/sites/ |
zone1_vigilant.tres + zone1_vigilant_terrain.res |
données du site |
tools/ (hors runtime) |
script de cuisson | produit le .res depuis une description de primitives géomorphologiques ; déterministe, versionné, jamais appelé par le jeu |
Les conventions du contrat : hauteur en mètres négatifs vers le bas, +X est,
-Z nord (convention Godot, convertie une seule fois dans
TerrainHeightField). Le terrain est stocké en SiteTerrainData au format
.res (élévations en float32 et matériaux en octets) produit par la recette
de cuisson ; le PNG 16 bits est écarté (ADR 0012). Ces points sont formalisés
dans l'ADR 0012 — terrain de site en champ de hauteur authoré, requis par
les guardrails §5 et §11 (nouveau contrat de données persistant dans le
dépôt).
vehicle_test_environment.gd perd sa formule analytique : la formule devient
le premier cas d'usage du script de cuisson, et la scène de test charge une
petite définition de site (fixture) comme le ferait le vrai site.
9. Pipeline d'auteur
- Graybox cuit (cette tranche) : une description déclarative des primitives (plateau, crête, pitons, sillon, rupture, tombant, rides) dans le script de cuisson. Itération en minutes, diff lisible, aucun outil externe. C'est « conçu à la main » : chaque forme est placée et nommée.
- Passe de sculpture (tranche 6) : export de la heightmap vers Blender, retouche manuelle, réimport. Le contrat ne change pas.
- Jamais de génération à l'exécution ni de dépendance à un plugin terrain ; si un plugin devenait souhaitable, ADR d'abord.
10. Tests
- Unitaires :
TerrainHeightField(interpolation bilinéaire, bornes, conversion monde ↔ cellule, matériau par cellule) ;PlayableBoundsRule. - Acteur : hauteur de collision égale à la hauteur du champ en plusieurs points, dont les quatre coins (ferme le doute du §2).
- Contrats sur
zone1_vigilant.tres: trois placements d'épave dans les limites ; cible et objets requis au-dessus de 60 m ; objet secondaire entre 60 et 69 m ; les amers listés sont uniques (pas deux crêtes de même signature) ; les deux routes existent sous forme de chemins de contrôle (liste de points) dont chaque point respecte sa profondeur annoncée et n'est pas dans la roche. - Intégration : charger le site, lancer un scan de référence depuis la position de départ et vérifier roche et sable dans le buffer ; un rayon vers le sillon touche le terrain ; temps de chargement sous 3 s.
- Humains (playtest tranche 3) : 8/10 trouvent l'accès en 5–10 min ; les testeurs nomment spontanément au moins un amer.
11. Ordre de construction
- ADR 0012,
DiveSiteDefinition,TerrainHeightFieldet leurs tests. BathymetricTerrainActoravec tuiles, collision et matériau sonar par position ; migration de l'environnement de test sur une fixture.- Script de cuisson et première cuisson du Banc du Vigilant (graybox) ;
bornes jouables ; scène générique
dive_site.tscnconfigurée par uneDiveSiteDefinition. - Shader triplanaire et props bornés.
- Points d'injection pour les trois épaves et le navire (les épaves elles-mêmes appartiennent au reste de la tranche 3).
Chaque étape laisse la barrière verte et la scène jouable.
12. Décisions demandées à Olivier
- Validation du plan de masse (§4.2–4.4) : trois épaves, deux routes, un tombant tentateur. Variante possible : déplacer le leurre 2 dans la Saignée pour piéger la route risquée.
- Objet secondaire à 62 m : garder la tentation sous la profondeur certifiée, ou le remonter à 55 m pour un premier site plus doux ?
- Pipeline : script de cuisson d'abord (recommandé) ou sculpture Blender dès le graybox ?
- Nom : « Banc du Vigilant » ou autre.