Tous les articles

Realsee réécrit entièrement son moteur de rendu 3D avec WebGPU : à la recherche de l’expérience 3D ultime

Realsee a entièrement réécrit son moteur de rendu spatial avec WebGPU pour viser l’expérience 3D ultime. Cet article examine les choix d’ingénierie de cette refonte, des panoramas, modèles texturés et tuiles de détail aux matériaux, plugins spatiaux, vues auxiliaires et sorties d’image.
Vues panoramiques et vue d’ensemble d’un modèle 3D texturé

Realsee a entièrement réécrit son moteur de rendu spatial avec WebGPU pour viser l’expérience 3D ultime. La réécriture couvre toute la chaîne : vues panoramiques et modèles, tuiles haute résolution, matériaux, plugins et sorties d’image.

La rotation d’un panorama, le zoom sur une surface, le passage entre points de capture et l’affichage d’un modèle texturé sollicitent tous le moteur de rendu. Pendant la visite, les annotations, les vidéos, les mesures et les parcours guidés doivent rester associés aux bons emplacements. [1]

Les ressources haute résolution doivent suivre la zone affichée. Le traitement des matériaux et des couleurs doit rester cohérent pour les images et les modèles. Le lecteur principal, les plugins spatiaux, les canevas auxiliaires et les captures d’écran doivent partager des règles communes pour les ressources et les sorties.

Ce qui distingue WebGPU de WebGL et WebGL 2

WebGL, WebGL 2 et WebGPU utilisent tous le GPU pour dessiner des scènes 3D. WebGL 2 étend les capacités graphiques de WebGL : le rendu instancié et les cibles de rendu multiples deviennent des fonctionnalités de base, auxquelles s’ajoutent les tampons d’uniformes, les textures 3D et le transform feedback. Ce dernier enregistre la sortie du vertex shader dans des tampons pour un traitement ultérieur. [2] [3]

WebGPU est conçu pour les API graphiques modernes comme Metal, Vulkan et Direct3D 12. Il réorganise les pipelines, les liaisons de ressources et la soumission des commandes, tout en donnant accès au calcul généraliste sur GPU. [4]

Critère WebGL WebGL 2 WebGPU
Modèle d’API OpenGL ES 2.0 OpenGL ES 3.0 Conçu pour les API GPU modernes
Fonctionnalités de base Rendu graphique Capacités graphiques et traitement des données étendus Rendu graphique et calcul généraliste sur GPU
Traitement des données sur GPU Algorithmes organisés autour des shaders et des textures Le transform feedback permet aussi d’enregistrer les résultats du traitement des sommets Pipelines de calcul, tampons de stockage en lecture et en écriture, groupes de travail
Organisation des tâches côté application Modifier l’état du contexte et lancer des appels de dessin Même modèle, enrichi notamment de tampons d’uniformes Pipelines et liaisons de ressources explicites ; encodage des commandes et soumission à une file
Langage de shader GLSL ES 1.00 GLSL ES 3.00, avec maintien de la prise en charge de la version 1.00 WGSL

Organiser et réutiliser explicitement l’état de rendu. WebGPU regroupe les shaders, la disposition des données de sommets, l’état de profondeur et l’état de mélange dans des objets pipeline. [5] Chaque appel de dessin sélectionne un pipeline et lui associe des ressources, ce qui permet de réutiliser une configuration fixe pour plusieurs tâches. Les tampons de commandes fournissent au navigateur et au pilote un lot de travail à planifier. Chrome cite la réduction du travail JavaScript pour un même rendu graphique parmi les principaux avantages de WebGPU. [6]

Donner au rendu graphique et au calcul des modèles de programmation adaptés. Les pipelines de calcul, les tampons de stockage et le lancement indirect des tâches permettent le traitement parallèle des données et d’autres algorithmes de rendu. [5] La consultation courante de panoramas et de modèles texturés utilise surtout le pipeline graphique : le CPU organise les ressources de la vue en cours, tandis que le GPU échantillonne les images, évalue les matériaux et dessine la scène.

Conserver la plage de luminosité étendue jusqu’à la sortie du canevas. Les panoramas contenant des données HDR doivent conserver les valeurs de hautes lumières reconstituées tout au long du rendu. Un canevas WebGPU en virgule flottante demi-précision, avec le mode de sortie extended, peut restituer ces valeurs sur un système d’affichage HDR compatible. [7] Les informations de luminosité du panorama peuvent ainsi être préservées jusque dans l’image finale.

Comment panoramas et modèles composent la vue

Les photographies panoramiques fournissent la couleur des surfaces ; le modèle fournit leur position dans l’espace et leur forme. Les matériaux du modèle déterminent où échantillonner l’image à partir de la position de la surface, ainsi que de la position et de l’orientation de prise de vue du panorama. Ils combinent cette couleur avec le résultat produit par les matériaux propres au modèle. Un fond panoramique complète aussi la vue au-delà des surfaces du modèle.

Le passage d’un point de prise de vue à un autre coordonne le déplacement de la caméra et les images. Les ressources du panorama précédent et du suivant participent à la mise à jour des matériaux. La position, l’orientation et le champ de vision de la caméra évoluent selon l’effet de déplacement choisi, tandis que les couleurs des deux panoramas suivent les règles de transition. Le passage à la vue du modèle modifie l’équilibre entre le rendu panoramique et celui des matériaux du modèle : l’attention passe du détail photographique à la structure d’ensemble. La migration des matériaux doit préserver à la fois ces relations d’échantillonnage et ces transitions.

Charger les détails nécessaires à la vue en cours

Le niveau de détail nécessaire au panorama dépend du champ de vision, des dimensions du canevas et du ratio de pixels. Ces données nous servent à choisir un niveau de tuiles. Le CPU détermine ensuite quelles tuiles intersectent le volume de vue de la caméra. Les requêtes donnent la priorité aux niveaux les moins détaillés, puis, au sein d’un même niveau, aux zones proches du centre de la vue, avec un nombre limité de chargements simultanés. Un zoom sur une fenêtre ou un mur donne ainsi la priorité aux détails utiles pour la vue en cours.

Le panorama de base fournit une image complète pendant que les nouvelles tuiles apparaissent en fondu. Ce fond et les tuiles haute résolution disponibles sont dessinés dans une texture de détail correspondant à la direction de vue. Les matériaux de la scène principale l’échantillonnent selon la projection correspondante. Cette texture de détail et l’image finale de la scène ont des rôles distincts : la première enrichit les matériaux panoramiques ; la seconde conserve le résultat du rendu de la scène pour la sortie et le post-traitement.

Un panorama de base et des tuiles de détail sélectionnées par le CPU composent une texture de détail, associée à la géométrie du modèle et aux médias spatiaux pour le rendu de la scène

La texture de détail alimente les matériaux panoramiques ; l’image de la scène alimente la sortie et le post-traitement éventuel.

Ce qu’implique la migration de l’ensemble du rendu

La migration de Realsee couvre la visite principale, les plugins spatiaux, les plans, les parcours guidés, les mini-cartes, les aperçus de produits et de modèles, ainsi que la production de captures d’écran et d’images de couverture. Certains composants disposent de leurs propres caméras et canevas ; d’autres dépendent de comportements établis pour les matériaux, les couleurs et les captures. Tous ces points d’entrée doivent fonctionner avec le nouveau système de rendu.

Préserver le résultat visuel lors du changement de matériaux

Le moteur WebGPU de Three.js utilise des matériaux à nœuds, ce qui impose de porter les matériaux GLSL personnalisés existants vers le Three.js Shading Language (TSL). TSL décrit les calculs d’ombrage comme une composition de nœuds et peut générer du WGSL ou du GLSL selon le backend choisi. [8]

Nous avons migré les matériaux des vidéos panoramiques, des lignes de guidage, des fonds de modèles des mini-cartes et des particules en préservant leurs projections, masques, fondus et comportements de profondeur. Les lignes de mesure révèlent un état facile à négliger : l’utilisateur a commencé une mesure, mais le premier segment n’est pas encore complet. La géométrie doit déjà présenter une disposition d’entrée valide, avec zéro instance visible tant que les deux extrémités ne sont pas disponibles.

Les dépendances entre paquets demandent la même attention. L’application hôte fournit Three.js au moteur principal et aux plugins spatiaux. Les builds des plugins laissent cette dépendance externe, et l’hôte définit sa version ainsi que le point d’entrée utilisé pour la résolution des modules. Les aperçus de modèles indépendants enregistrent les mêmes correspondances entre modèles et matériaux que le moteur principal, afin d’associer les modèles chargés aux matériaux à nœuds appropriés.

Vérifier les couleurs et la transparence à chaque étape de composition

Une vidéo peut sembler plus claire après un changement de moteur de rendu. Nous avons identifié un cas où une vidéo encodée en sRGB était traitée comme une couleur linéaire, puis encodée une seconde fois en sortie. Nous l’avons corrigé en déclarant l’espace colorimétrique de la texture vidéo, pour distinguer le décodage à l’entrée de la conversion finale en sortie. La documentation Three.js sur les textures vidéo précise cette exigence d’entrée. [9]

Les médias transparents, les lignes de guidage et les annotations enregistrées doivent aussi se composer correctement avec l’arrière-plan. Les médias transparents définissent séparément le mélange des couleurs et celui du canal alpha ; les lignes conservent le fond déjà dessiné. Les annotations enregistrées traitent l’espace de travail et l’encodage d’affichage au moment de la composition, afin de préserver la signification des couleurs stockées. Les couleurs d’entrée, l’espace de travail linéaire et l’encodage d’affichage doivent être cohérents ; un simple ajustement de luminosité peut masquer une erreur dans ces conversions. [10]

Gérer l’initialisation, la libération des ressources et la récupération du périphérique

L’initialisation du moteur WebGPU est asynchrone. [8] Les aperçus de modèles et les boussoles autonomes attendent sa fin avant de créer les ressources qui en dépendent ou de dessiner. Lorsqu’un utilisateur passe rapidement d’un aperçu à l’autre, un modèle chargé doit toujours correspondre à la requête en cours. Les résultats devenus obsolètes sont libérés, pour que la vue réponde à la dernière action.

La fermeture d’un aperçu de produit annule d’abord les requêtes et les animations, puis supprime les écouteurs d’événements. L’instance et le canevas sont libérés une fois l’initialisation terminée. La perte du périphérique GPU suit une autre séquence de récupération. La vue principale sauvegarde l’état de navigation, libère l’ancienne session et en crée une nouvelle ; elle rétablit la vue et l’étage au fil du chargement des ressources. Les canevas de plugins qui utilisent notre composant commun de rendu autonome recréent leur moteur, rétablissent les dimensions, le ratio de pixels et le fond transparent, puis remplacent le canevas affiché lorsque la nouvelle instance est prête. La vue principale et ces canevas de plugins reconstruisent chacun les ressources qui leur appartiennent.

Restituer l’image rendue dans les captures d’écran

Cette chaîne de capture dessine la région demandée dans une cible RGBA8, puis relit les pixels de manière asynchrone du GPU vers le CPU. Lorsque la commande WebGPU copyTextureToBuffer copie plusieurs lignes de ces pixels, le pas entre les lignes doit être un multiple de 256 octets. Par exemple, une image RGBA8 de 100 pixels de large contient 400 octets de données de couleur par ligne et peut utiliser un pas de copie de 512 octets. Le traitement d’image a ensuite besoin des 400 octets utiles de chaque ligne. [5]

La couche de relecture vérifie la longueur des données reçues : elle copie directement les données compactes et extrait les pixels utiles ligne par ligne lorsqu’un remplissage est présent. L’hôte normalise ensuite l’orientation des lignes selon le comportement du backend du SDK utilisé. Les coordonnées de recadrage conservent leur origine en bas, tandis que les lignes de sortie sont ordonnées de haut en bas pour le canevas de l’image. Les recadrages et les images de couverture partagent cet adaptateur, et les éléments auxiliaires masqués pour la capture sont rétablis ensuite.

Réutiliser une image tant qu’elle reste valide

La réutilisation d’images et les mises à jour à la demande s’appliquent aussi bien à WebGL 2 qu’à WebGPU ; le moteur de rendu en définit les règles. Une caméra peut rester immobile pendant qu’un effet animé continue de fonctionner. Reconstruire toute la scène à chaque mise à jour de cet effet répéterait un travail dont le résultat n’a pas changé.

Nous dessinons la scène dans une image intermédiaire, puis appliquons les effets de post-traitement. Tant que cette image reste valide, les effets peuvent continuer à l’utiliser.

Les mises à jour suivent les règles suivantes :

Changement Travail nécessaire
La caméra ou la scène change Reconstruire l’image de la scène pour la nouvelle vue
Une image est chargée ou une nouvelle image vidéo arrive Demander une mise à jour pour intégrer le nouveau contenu
Au moins un effet reste actif, et le nombre d’effets actifs ou les types d’entrées nécessaires changent Préparer à nouveau le résultat de composition correspondant
Le dernier effet de post-traitement est désactivé L’application demande une mise à jour pour afficher l’image sans cet effet
Les dimensions de la zone d’affichage changent Reconstruire les ressources de sortie et composer l’image aux nouvelles dimensions
Seul un effet animé de post-traitement change Réutiliser l’image de la scène et poursuivre la mise à jour de l’effet

Le code appelant doit demander une image lors d’un changement d’effets. Lorsque le dernier effet de post-traitement est désactivé, cette image présente le résultat sans lui. Ensuite, si le post-traitement est désactivé et que la scène ne change pas, le moteur peut éviter de dessiner une nouvelle image. Les effets encore actifs continuent de lire l’image conservée de la scène, avec de nouvelles commandes encodées et soumises selon les besoins.

Conserver des images intermédiaires consomme de la mémoire GPU, et le format influe sur la quantité de données lues et écrites. Prenons la texture qui reçoit la sortie couleur — un attachement couleur de la cible de rendu — en 1920 × 1080, avec une seule couche, un échantillon par pixel et aucun mipmap. RGBA8 possède quatre canaux de 8 bits ; RGBA16F, quatre canaux en virgule flottante de 16 bits. Le décompte des texels, les pixels de la texture, donne : [5]

Format de couleur Octets par texel width × height × bytes Stockage
RGBA8 4 1920 × 1080 × 4 Environ 7,9 MiB
RGBA16F 8 1920 × 1080 × 8 Environ 15,8 MiB

Un MiB représente 1 048 576 octets. Les données de profondeur, les copies de tampons supplémentaires, les autres attachements et l’alignement des allocations s’ajoutent à ces quantités. Doubler les deux dimensions quadruple le stockage des couleurs à format identique. Ces chiffres décrivent le stockage des texels de couleur. Les coûts de lecture et d’écriture dépendent aussi de la manière dont la séquence de rendu accède à ces textures. Le choix d’une précision de sortie tient donc compte de la capacité et des modes d’accès, ainsi que du compromis entre qualité, mémoire et bande passante décrit par Three.js. [11]

Les ressources des tuiles ont leur propre politique de réutilisation. Les tuiles récemment utilisées peuvent continuer à fournir des textures tant qu’elles restent dans le cache ; leurs ressources sont libérées lorsqu’elles en sortent. Lorsqu’un objet texture est nécessaire, le pool de réutilisation recherche une correspondance de dimensions et d’espace colorimétrique. Les détails chargés restent ainsi disponibles, tout en conservant la bonne interprétation des images couleur et des textures de données.

Maintenir la lecture vidéo dans un moteur de rendu à la demande

Un moteur de rendu à la demande doit être informé des changements de la scène. Une vidéo intégrée à un panorama produit du nouveau contenu même lorsque la caméra est immobile : le composant média doit donc en avertir le moteur.

Un événement de lecture ne signifie pas toujours qu’une image est prête à être dessinée. Avant d’ajouter la vidéo à la scène, notre composant vérifie qu’une image est exploitable et que la vidéo appartient bien au panorama affiché. Pendant la lecture, il continue de demander des rendus de la scène et marque la texture vidéo pour mise à jour lorsque celle-ci n’a pas avancé. Le média peut ainsi continuer à s’animer même lorsque la caméra reste immobile.

La mise en pause annule la planification des rendus utilisée pendant la lecture. La destruction du composant libère sa texture vidéo, sa géométrie et son matériau. Les événements tardifs de lecture, de pause ou de déchargement sont traités en fonction de l’état actuel du composant, pour qu’une ancienne session de lecture ne perturbe pas la nouvelle image.

Prendre en charge WebGPU et WebGL 2

La disponibilité de WebGPU dépend du navigateur, du système d’exploitation et du GPU. Le navigateur doit exposer l’API et fournir un périphérique GPU utilisable doté des capacités requises. [6] [4]

Le moteur WebGPU de Three.js prend en charge les backends WebGPU et WebGL 2. [11] Realsee conserve les chemins de rendu correspondants et vérifie le backend actif après l’initialisation. Panoramas, modèles et composants spatiaux utilisent des matériaux et des ressources compatibles ; la sortie des captures d’écran est elle aussi adaptée au backend.

L’application relie les déplacements de la vue, les changements de mode et les mises à jour des médias au backend choisi. Un même contenu peut être dessiné selon différentes méthodes, chaque effet étant adapté aux capacités du chemin de rendu utilisé.

Essayer les paquets WebGPU sur npm

Commencez à créer une application de visualisation spatiale avec Five WebGPU sur npm. Le SDK principal publie sa version WebGPU sur le canal alpha. Cet article utilise la version 1.0.0-alpha.11 avec three@0.183.2. [12]

npm install --save-exact three@0.183.2 @realsee/five-webgpu@1.0.0-alpha.11

Pour les annotations spatiales, les mesures, les parcours guidés et les autres plugins, ajoutez la version WebGPU de Dnalogel. Cet article utilise la version 4.0.0-webgpu.6, avec la même instance de Three.js que le SDK principal. [13]

npm install --save-exact @realsee/dnalogel@4.0.0-webgpu.6

Découvrez des visites publiques de restaurants, de logements, de musées et de commerces sur Realsee Discover. [14]

Consultez la plateforme de développement Realsee pour découvrir ses capacités de visualisation spatiale et créer vos propres applications.

Références