Mesure la fréquentation de www.aidesktopstudio.com, avec consentement - #5
Merged
Merged
Conversation
…elles scènes Étape 1 du chantier C6 (moteur de rendu). - `RenderPolicy.csm`, désactivé par défaut, et `csm.ts` qui enveloppe l'addon `CSM` : trois lumières de cascade, le soleil du document retiré du casting, les matériaux habillés une seule fois et remis en état à la libération. Réglage exposé dans l'espace 3D, dépendant de « Ombres portées ». - Les textures sont lues avec `capabilities.getMaxAnisotropy()` : le filtrage anisotrope coûte de la bande passante d'échantillonnage, pas un octet de mémoire de texture, donc plafonner sous ce que la carte offre ne rend rien. - `agx` rejoint `ToneMapping` et devient la courbe des scènes CRÉÉES, via `NEW_SCENE_WORLD` ; `DEFAULT_WORLD` reste sur `none`, donc un projet relu s'ouvre exactement comme il a été écrit. Le point 1.1 du spec n'est pas appliqué et c'est mesuré, pas un arbitrage : `WebGLProgram.shadowMapTypeDefines` de three 0.185 ne nomme que PCF et VSM, donc `PCFSoftShadowMap` retombe sur `SHADOWMAP_TYPE_BASIC` — une comparaison non filtrée, `shadow.radius` ignoré. `PCFShadowMap` EST le mode doux (disque de Vogel à cinq taps). Le commentaire de `MAP_TYPES` porte la vérification.
…/ Avancé Étape 2 du chantier C6 : l'interface, pas encore de contenu GPU. `RenderDriver` (engines/render/) couvre les quatre points qui dépendent de l'API graphique et rien d'autre : construire le renderer, relire ses pixels, préfiltrer l'environnement, patcher le matériau standard. Même forme que `game/ports/` : l'interface d'un côté, chaque implémentation dans son fichier. - `glDriver` enveloppe le code existant tel quel — `readRenderPixels`, `environment.ts` et le patch de `materialShader` passent derrière sans que leur logique bouge ; un projet `gl` dessine exactement ce qu'il dessinait. - `gpuDriver` refuse les quatre appels sur la même phrase localisée. - `mountRenderer` retombe sur Compatible quand Avancé lève ou qu'aucun adaptateur n'a répondu : jamais d'écran noir, une trace `render.fallback` qui ne remonte pas en toast — l'image est juste, rien n'est perdu. - `gpuAdapter` interroge `navigator.gpu?.requestAdapter()` une seule fois. C'est le SEUL signal qui décide ; `adapter.info` n'entre pas dans le choix. - `PostEffectMeta.engines` : les trente effets existants sont `['gl']`. Les slots et la règle d'exclusivité ne bougent pas. `readPixels` rend une promesse des deux côtés bien que WebGL réponde tout de suite : la lecture GPU mappe un buffer et résout une frame plus tard, et les trois appelants étaient déjà dans un chemin asynchrone. Écart assumé sur le MUST 7 : `RenderPolicy` vit dans `Settings.three`, un réglage d'application, et la création de projet est un choix de dossier sans dialogue. Le sélecteur est donc dans l'espace 3D des préférences, et le verrou « pas de switch en direct » tient par construction — le moteur est lu au montage du viewport, ce que dit son texte d'aide.
…ises d'aplomb
Ce que `pnpm check` puis `pnpm validate` ont trouvé sur les deux étapes.
- `postParamSpec.ts` sort du registre les six fabriques de spec et leurs types :
520 lignes pour une limite à 500 une fois `engines` posé sur trente fiches.
- `mountRenderer.ts` sort de `renderDriver.ts` : les implémentations importent
l'interface, un chooseur posé à côté d'elle fermait le graphe en cycle.
- `cascadesMoved` sort de `configure`, qui dépassait la complexité autorisée.
- Zod ignorait `three.engine` et `three.csm` : un réglage absent du schéma est
effacé silencieusement à l'écriture, et `validation.test.ts` le disait.
- `fakeRenderer()` rejoint les fixtures viewport : neuf points stubaient `gl`
par `{}`, ce qui ne répond plus depuis que le cache lit `getMaxAnisotropy`.
- Le banc 48.4 vérifiait « une courbe est active », désormais vrai du décor
lui-même : il vérifie aussi l'APPEL. `sceneWorld` citait `agx` comme mot
inconnu du build — remplacé par un mot qui l'est encore.
- Typographie française des deux nouveaux textes de réglage.
`RAPPORT-C6.md` : `docs/fr/audits/moteur-rendu-c6/RAPPORT.md`. L'étape 3 n'est
pas livrée et le rapport dit pourquoi, mesures à l'appui.
…lles n'éclairaient Cinq relectures indépendantes (réutilisation, simplification, efficacité, altitude, code-review). Ce qui a été retenu, du plus grave au moins : - **Les cascades sur-éclairaient la scène d'environ dix fois.** `CSM` ajoute trois lumières à 3 d'intensité chacune, et le soleil du document continuait d'éclairer à côté. Les bandes REMPLACENT désormais le soleil : sa couleur et son intensité passent sur elles, il cesse d'éclairer et de projeter, et `release` lui rend les deux. Pas de division par trois : le chunk n'éclaire un fragment que depuis la bande où tombe sa profondeur. - **Le terrain perdait ses deux ombres.** `dress` sautait tout matériau portant un `onBeforeCompile`, c'est-à-dire le splat de relief — donc pas de cascades ET plus de carte du soleil, sur le seul cas que les cascades servent. Les deux crochets se composent maintenant, et `release` ne rend le sien qu'à un matériau que personne n'a réattaché depuis. - **Un orbite affichait des ombres périmées** : `follow` répond si les bandes ont bougé, et `dressPane` remonte cette réponse — c'est ce qui dit à la frame que la passe d'ombres vaut d'être jouée. - **Les rendus hors écran** (film, capture de vol, validation) ne recadraient jamais les bandes : elles restaient ajustées à la vue de l'éditeur. - **L'export jeu ignorait `csm`** : `webRender` construit les mêmes cascades. - Le garde de `aim` comparait x et z d'un vecteur brut contre un normalisé : un soleil qui ne bougeait qu'en y ne recadrait jamais. - Habillage limité aux nœuds changés plus les lots instanciés, au lieu d'un `traverse` complet à chaque `applyState` — y compris par frame de jeu. - `follow` recadrait par identité de caméra : quatre recadrages par frame en quadrant, chacun parcourant tous les matériaux habillés. C'est la PROJECTION qui est comparée. - `materialsOf` remonte dans `shadows.ts`, partagé par les deux passes qui marquent les mêmes matériaux ; `NEW_SCENE_WORLD` retrouve son gel ; zod ignorait deux réglages ; l'anisotropie ne descend plus sous 1 (three répond 0 sans l'extension) ; `driverFor` n'est plus exporté. - L'aide du sélecteur dit désormais que le moteur Avancé n'est pas encore construit et que le choisir dessine en Compatible. Refusés, avec le motif : retirer `engines` du registre et le réglage `engine` (deux revues le demandent — le spec les exige à cette étape), et retirer la sonde d'adaptateur (MUST 5, avec son test).
…n nœuds Étape 3 du chantier C6. Le moteur Avancé dessine réellement, mesuré sur cette machine (M2 Max, adaptateur WebGPU présent). - `gpuModule` charge `three/webgpu`, TSL et les nœuds d'affichage à la demande, une seule fois, et seulement là où un adaptateur a répondu : deux mégaoctets de renderer ne sont jamais cherchés sur une machine qui ne peut pas s'en servir. `three/webgpu` et `three` partagent `three.core.js`, donc le renderer de nœuds dessine les scènes que le studio construit déjà. - `materialNodes` réécrit le patch matériau en TSL. Deux écarts assumés : plus aucune recompilation quand un canal se remplit (un uniforme remplace le `#ifdef`), et la cavité tombe sur la couleur diffuse faute de couture sur `reflectedLight` — identique sur un diélectrique, un peu plus sombre sur un métal. Les uniformes sont ceux du moteur, partagés, pas copiés. - `gpuComposer` bâtit un `RenderPipeline` : passe de scène en MRT avec ses normales, puis `ao()` natif multiplié dedans. `gtao.engines` passe à `['gl','gpu']`. Aucune fusion façon `fuseShader` : le pipeline partage déjà profondeur et normales. - `gpuPostQuality` est DÉRIVÉ de `postQuality`, jamais une seconde table : le même réglage achète la même chose des deux côtés. - Lecture de pixels par `readRenderTargetPixelsAsync`, sous la signature promise dès l'étape 2. Les trois appelants n'ont pas bougé. - `StudioRenderer` élargit le type du renderer sur toute la chaîne viewport. Les différences réelles sont nommées une par une : pas de porte globale sur la passe d'ombres, pas de minuterie GPU, pas de `forceContextLoss`, l'anisotropie lue à deux endroits, les échantillons MSAA à zéro. Trois pannes trouvées en faisant tourner le banc, pas en relisant le code : le montage demandait son contexte WebGL2 au renderer de nœuds avant son init, la scène préfiltrait la salle neutre avant l'init, et les images n'étaient pas retenues tant que le backend n'était pas là. Banc : `pnpm engines:bench`, harnais navigateur piloté par CDP, comme `world:validate`. Chiffres dans le rapport, y compris celui qui dérange : sur ces deux profils l'Avancé coûte plus cher côté CPU (0,12 ms contre 0,045 à 0,080) et n'est plus rapide sur rien. Il ne se dégrade pas avec la scène, lui, mais aucun seuil de gain n'est atteint et le rapport le dit tel quel. TRAA écarté, motif écrit : pas de jumeau GL, donc pas de place dans un catalogue partagé sans une UI par moteur, que le spec met hors périmètre.
…lée et à l'envers Revue de correction (neuf défauts, tous dans le chemin GPU) et revue de simplification. Du plus grave au moins : - **La lecture de pixels rendait des lignes paddées et à l'endroit.** WebGPU copie une texture vers un buffer en alignant chaque ligne sur 256 octets, et les rend de haut en bas ; le Compatible les rend serrées et de bas en haut, et l'encodeur de film retourne sans condition. Toute capture Avancé sortait donc retournée, et cisaillée dès que la largeur n'était pas un multiple de 64 pixels. `sameShapeAsGl` rend une seule forme aux deux moteurs. - **La chaîne gelait sa caméra.** Le GL réattache scène et caméra à chaque dessin ; un chaînage de nœuds les cuit dans le graphe. Un film dont la liste de plans change de caméra en cours continuait sur la première. La caméra entre dans la chaîne et la fait reconstruire quand elle bouge. - **`RenderPipeline.dispose` ne libère que son quad** : chaque chaîne évincée fuyait un G-buffer plein écran. La passe est libérée à la main avec elle. - **`colorNode` écrasait la carte de couleur de base** : tout matériau texturé aurait rendu plat. C'est `materialColor` qu'il faut multiplier, pas la teinte. - **Les deux cartes remappées lisaient sans leur matrice** : une rugosité tuilée lisait non tuilée pendant que le masque de cavité à côté tuilait — exactement le décalage que `syncEdgeTransform` existe pour empêcher. - **La cible de SORTIE manquait** : une passe de nœuds se dimensionne sur le drawing buffer faute de mieux, donc un film 1920×1080 se composait dans un G-buffer de la taille du canevas. Et rien ne restaurait viewport ni ciseaux. - Le montage pouvait armer un renderer sur la réponse du précédent ; `settled()` résout aussi sur un refus, donc l'éclairage attend `canDraw`, pas la promesse. Revue de simplification, retenu : une seule déclaration de `ComposerJob` pour les deux chaînes (elle était copiée champ par champ), `ROOM_SIGMA` et `BOTH_ENGINES` déduplitués, les quatre capacités qui différaient entre moteurs (`maxSamples`, `maxAnisotropy`, `frameTimer`, `releaseContext`) passent dans `RenderDriver` — cinq `'capabilities' in renderer` disparaissent, dont un qui vivait dans le fichier d'interface lui-même. TRAA est retiré jusqu'à son lot : son module de nœuds n'était plus chargé pour rien, ni son champ de budget lu par personne. Le banc moyenne désormais dix images fixes : un échantillon unique variait du simple au double. Chiffres du rapport remesurés sur cette révision, et une affirmation du tour précédent corrigée — l'Avancé monte moins vite avec la scène, mais il monte.
`pnpm engines:parity` rend la même scène de référence sur le Compatible et sur l'Avancé et compare pixel à pixel, dans le harnais que `world:validate` utilise déjà entre deux représentations. Six cas, chacun par la couture que le studio emprunte lui-même : la scène nue, la même sous GTAO, la capture d'export, une image de film, le patch matériau et la règle temporelle. Mesuré le 11 septembre 2026, fenêtre au premier plan : scène nue 0 % de pixels différents, film 642x362 0 %, export 0,22 %, GTAO 2,7 %. Le patch matériau diffère de 24,75 % — l'écart connu, la cavité tombant sur la couleur diffuse côté nœuds. Le harnais refuse de mesurer sans image d'animation : une fenêtre derrière une autre n'en reçoit aucune, et les deux moteurs y dessinent autrement — 58 % d'écart sur une scène identique, mesuré. Le moteur vit désormais dans le DOCUMENT (`SceneWorld.engine`), choisi à la création et relu à chaque montage ; la préférence ne fait plus que pré-remplir le champ. L'export jeu lit celui de la scène d'entrée. TRAA est porté, sans paramètre — three 0.185 n'expose aucun nombre d'échantillons — et la bibliothèque d'effets ne propose plus ce que le moteur du document ne sait pas bâtir. Ce que la comparaison a trouvé, que le banc ne pouvait pas voir parce qu'il mesurait ce que la chaîne coûte et non ce qu'elle dessine : - l'occlusion sortait ROUGE : `GTAONode` rend dans une cible `RedFormat`, donc `getTextureNode()` donne (ao, 0, 0, 1) et multiplier ça tuait le vert et le bleu ; - `blend` ne faisait rien côté Avancé, alors que le `GTAOPass` GL l'applique ; - un effet temporel donnait une image PLATE à l'export : bâtie, dessinée puis libérée, la chaîne ne lui laisse aucun historique. `PostEffectMeta.temporal` le déclare et le composeur laisse ces effets hors d'une image unique. Et ce que la revue a trouvé ensuite, dont un défaut haut : un document en Avancé n'obtenait jamais le moteur Avancé dans la session qui l'ouvre — le viewport lançait le chargement du bundle puis demandait s'il était là, sur la ligne suivante. `useRenderEngineReady` retient le montage jusqu'à ce que ce chargement aboutisse. Suivent la cible de l'occlusion qui fuyait, la chaîne abandonnée quand une pile change de forme, `maxSamples` qui répondait à deux questions et faisait perdre son anticrénelage à une capture, l'applicateur manquant qui aurait décalé les paramètres d'un effet sur la passe d'un autre, et un soleil remplacé qui laissait la scène éclairée deux fois. Rapport : docs/fr/audits/moteur-rendu-c6/RAPPORT.md
…e, et corrige ce que ça révèle
La porte a viré au rouge sur `develop` : `check-as-const` lit `git ls-files`, donc il ne voit pas un fichier neuf tant qu'il n'est pas indexé. La validate lancée avant le premier `git add` était aveugle à ce test, qui figeait son paramètre avec `as const` et le rerendait avec un `as unknown as`. Annoter l'argument de `renderHook` supprime les deux d'un coup.
…e figer avec `as const`
…ort ce qu'il affirmait sans le tenir
Relecture du chantier C6. Six énoncés du rapport ne tenaient pas devant le code :
un fichier de test qui n'existe pas (`renderDriver.test.ts`), une colonne de banc qui
n'existe pas (`readbackMs`), trois nombres de tests gonflés, des plafonds de porte
présentés comme des mesures arrondies alors que ce sont des marges, un critère
d'acceptation (« un projet existant est identique ») démenti par l'anisotropie maximale
de sa propre étape, et l'export jeu présenté comme honorant le moteur du document alors
que `createWebRender` construit un `WebGLRenderer` sans jamais lire `policy.engine`.
Un défaut, corrigé : les cascades se construisaient sur le moteur Avancé. `CSM` passe par
`onBeforeCompile`, que seul `WebGLRenderer` appelle — three 0.185 ne le nomme nulle part
sous `renderers/common` ni `renderers/webgpu`. Le patch n'atteignait aucun programme
pendant que `dress` éteignait le soleil du document et posait trois bandes à son
intensité : scène éclairée trois fois, ombre perdue. `cascadesWanted(policy, engine)`
porte désormais la règle, et le port de jeu la lit au lieu de la réécrire.
/simplify, quatre angles :
- `gpuComposer` tenait deux maps pour une relation une-à-une ; la clé contenant déjà la
surface, les deux gardes `[...bound.values()].includes(...)` protégeaient un cas
impossible. Une `Map<surface, {shape, chain}>` suffit.
- `gpuSamplesOf` fabriquait un `divisor` que `samplesOf` ne lit jamais : `samplesOf`
s'élargit à `Pick<PostBudget, 'samples'>` et la fonction disparaît.
- `drawOverlay` rejoint `RenderDriver` : `'capabilities' in renderer` au point d'appel
était l'expression que l'en-tête du driver cite comme ce qu'il existe pour empêcher.
- `asNodeTarget` était écrit deux fois, JSDoc comprise ; il rejoint `drawInto`.
- Le banc réutilise `mountedScene`, `offScreenHost` et l'attente d'images du harnais de
parité au lieu de les réécrire ; `messageOf` remplace deux copies.
- `mountRenderer` perd un troisième état que seul le test exerçait.
Cinq coûts par image relevés et NON MESURÉS sont écrits dans le rapport plutôt que
corrigés à l'aveugle : ils demandent `pnpm engines:parity` sur une machine WebGPU.
`pnpm validate` verte en 174 s.
La map unique du commit précédent réécrivait son entrée à chaque image : en régime
établi, `{ shape, chain }` reconstruit était identique à celui qu'il remplaçait. La
réponse se donne maintenant avant toute écriture — un objet et un `Map.set` de moins
par surface et par image, sur le chemin à 60 Hz.
Constat de la revue d'efficacité, introduit par la simplification elle-même.
…uteur `policy.engine` voyage dans le manifeste et `webRender` ne le lit nulle part : un jeu fait sur le moteur Avancé joue en WebGL. Le champ était rempli par `gameExportCompiler`, relu par `readRenderPolicy`, et ignoré en silence. L'honorer demande de porter le bundle de nœuds dans une page exportée — un chantier à part. Ce qui pouvait être corrigé ici l'est : le jeu le DIT au chargement, par le port de journal que `webRender` ouvre déjà pour la chaîne d'effets qui ne bâtit pas, et sur la même doctrine — un jeu qui joue sans ce que son auteur a demandé le dit au lieu de jouer quand même. Le rapport note au passage un critère d'acceptation de l'étape 2 qui n'a jamais été mesuré : « un projet `'gl'` est bit-identique à avant ce chantier ». Aucun banc du dépôt ne compare une révision à la précédente ; `engines:parity` compare les deux moteurs entre eux. `pnpm validate` verte en 167 s.
…t de refuser Six constats de `/code-review`, tous retenus. Le seul qui coûtait une image : en passant `'gl'` en dur à `cascadesWanted`, le port de jeu bâtissait les cascades d'un document Avancé pendant que l'éditeur les lui refusait — même scène éclairée de deux façons, ce que le commentaire d'`exportRequestOf` désigne comme l'accident à ne pas avoir. C'est le moteur du DOCUMENT qui décide des deux côtés. Le refus était par ailleurs muet : « Ombres en cascade » reste une préférence offerte, et sur un document Avancé elle ne changeait plus rien sans le dire. Elle le dit maintenant au journal, par la même trace que le repli de moteur, dans les quinze langues. Quatre suivis de texte : un test de `gpuPostQuality` devenu tautologique après la suppression de `gpuSamplesOf` (il n'assertait plus que ce que son voisin assertait déjà), deux références du rapport fausses depuis leur propre commit (`sayEngineIgnored` renommé `policyOf`, « cinq cas » devenus quatre), et `run-engine-parity.mjs` qui gardait sur ses plafonds l'affirmation que le rapport venait de corriger. `pnpm validate` verte en 185 s, 0 lien caché.
… cascades que l'éditeur venait de refuser
Une ligne dans le gabarit, donc dans les quinze langues à la fois : le bandeau de choix et le chargement de Google Analytics vivent dans un seul fichier partagé, servi par www.pasquelin.com et commun aux quatre sites. Une correction s'y fait une fois et non quatre ; son code et ses tests sont dans le dépôt `pasquelin/site`, sous `public/shared/`. Rien n'est demandé à Google avant un accord explicite du visiteur, et le panneau emprunte les couleurs, la police et les arrondis de cette page plutôt que d'imposer les siens. Propriété GA4 : G-YRFNHZLMJH — un identifiant de mesure n'est pas un secret, toute page qui le porte le montre à qui lit sa source.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Une ligne dans le gabarit, donc dans les quinze langues à la fois.
Le bandeau de consentement et le chargement de Google Analytics vivent dans un seul fichier partagé, servi par www.pasquelin.com et commun aux quatre sites ; son code, ses traductions et ses tests sont dans le dépôt
pasquelin/site, souspublic/shared/. Une correction s'y fait une fois et non quatre.Rien n'est demandé à Google avant un accord explicite du visiteur : le mode Consentement est armé sur
deniedetgtag.jsn'est même pas téléchargé. Le panneau emprunte les couleurs, la police et les arrondis de la page plutôt que d'imposer les siens — vérifié sur le rendu construit de ce site.Propriété GA4 :
G-YRFNHZLMJH, dans le compte Analytics « Site perso ». Un identifiant de mesure n'est pas un secret : toute page qui le porte le montre à qui lit sa source.