1. Présentation
Les graphiques 3D sont un élément fondamental de nombreuses applications, y compris les jeux, la conception et la visualisation de données. À mesure que les processeurs graphiques et les outils de création continuent de s'améliorer, les modèles 3D plus grands et plus complexes deviendront monnaie courante et contribueront à alimenter de nouvelles applications dans la réalité virtuelle (RV) et la réalité augmentée (RA) immersives. En raison de cette complexité accrue des modèles, les exigences en termes de stockage et de bande passante doivent suivre le rythme de l'explosion des données 3D.
Avec Draco, les applications utilisant des graphiques 3D peuvent être beaucoup plus petites sans compromettre la fidélité visuelle. Pour les utilisateurs, cela signifie que les applications peuvent désormais être téléchargées plus rapidement, que les graphiques 3D dans le navigateur peuvent se charger plus vite et que les scènes de réalité virtuelle et augmentée peuvent désormais être transmises avec une fraction de la bande passante, rendues rapidement et avoir un rendu fantastique.
Qu'est-ce que Draco ?
Draco est une bibliothèque permettant de compresser et de décompresser des maillages et des nuages de points géométriques 3D. Il vise à améliorer le stockage et la transmission des graphiques 3D.
Draco a été conçu et développé pour offrir une compression efficace et rapide. Le code permet de compresser les points, les informations de connectivité, les coordonnées de texture, les informations de couleur, les normales et tout autre attribut générique associé à la géométrie. Draco est publié en tant que code source C++ qui peut être utilisé pour compresser des graphiques 3D, ainsi que des décodeurs C++ et JavaScript pour les données encodées.
Objectifs de l'atelier
- Utiliser Draco pour compresser un modèle 3D
- Utiliser différents modèles de compression et leur impact sur la qualité et la taille du modèle
- Afficher un modèle 3D sur le Web
Prérequis
- Une version récente de Chrome
- L'exemple de code
- Un éditeur de texte
- Python
- cmake
2. Configuration
Clonez le dépôt GitHub à l'aide de cette ligne de commande :
git clone https://github.com/google/draco
Accédez au répertoire racine de Draco.
cd draco
3. Créer l'encodeur
Pour commencer à encoder et décoder avec Draco, commençons par créer les applications.
Compiler l'encodeur
- Exécutez cmake à partir d'un répertoire dans lequel vous souhaitez générer des fichiers de compilation, et transmettez-lui le chemin d'accès à votre dépôt Draco.
mkdir build
cd build
cmake ../
make
4. Encoder votre premier composant 3D
draco_encoder lit les fichiers OBJ ou PLY en entrée et génère des fichiers encodés au format Draco. Nous avons inclus le maillage Bunny de Stanford pour les tests. La ligne de commande de base se présente comme suit :
./draco_encoder -i ../testdata/bun_zipper.ply -o bunny.drc
Vous pouvez maintenant examiner la taille du fichier de sortie et la comparer à celle du fichier .ply d'origine. Le fichier compressé doit être beaucoup plus petit que le fichier d'origine.
Remarque : La taille compressée peut varier en fonction des options de compression.
5. Décoder un fichier Draco dans le navigateur
À ce stade, nous allons commencer par une page Web de base pour décoder les fichiers Draco. Nous allons commencer par copier et coller les sections de code suivantes dans l'éditeur de texte.
- Commencez par un fichier HTML de base.
<!DOCTYPE html>
<html>
<head>
<title>Codelab - Draco Decoder</title>
- L'extrait de code suivant chargera le décodeur Draco WASM.
<script src="https://www.gstatic.com/draco/versioned/decoders/1.4.1/draco_wasm_wrapper.js">
// It is recommended to always pull your Draco JavaScript and WASM decoders
// from the above URL. Users will benefit from having the Draco decoder in
// cache as more sites start using the static URL.
</script>
- Ajoutez ensuite cette fonction, qui créera un module de décodage Draco. La création du module de décodage est asynchrone. Vous devez donc attendre que le rappel soit appelé avant de pouvoir utiliser le module.
<script>
'use strict';
// The global Draco decoder module.
let decoderModule = null;
// Creates the Draco decoder module.
function createDracoDecoderModule() {
let dracoDecoderType = {};
// Callback when the Draco decoder module is fully instantiated. The
// module parameter is the created Draco decoder module.
dracoDecoderType['onModuleLoaded'] = function(module) {
decoderModule = module;
// Download the Draco encoded file and decode.
downloadEncodedMesh('bunny.drc');
};
DracoDecoderModule(dracoDecoderType);
}
- Ajoutez la fonction permettant de décoder un maillage encodé Draco.
// Decode an encoded Draco mesh. byteArray is the encoded mesh as
// an Uint8Array.
function decodeMesh(byteArray) {
// Create the Draco decoder.
const decoder = new decoderModule.Decoder();
// Create a buffer to hold the encoded data.
const buffer = new decoderModule.DecoderBuffer();
buffer.Init(byteArray, byteArray.length);
// Decode the encoded geometry.
let outputGeometry = new decoderModule.Mesh();
let decodingStatus = decoder.DecodeBufferToMesh(buffer, outputGeometry);
alert('Num points = ' + outputGeometry.num_points());
// You must explicitly delete objects created from the DracoModule
// or Decoder.
decoderModule.destroy(outputGeometry);
decoderModule.destroy(decoder);
decoderModule.destroy(buffer);
}
- Maintenant que nous avons la fonction de décodage Draco en place, ajoutons une fonction pour télécharger un maillage encodé Draco. La fonction "downloadEncodedMesh" accepte un paramètre pour le fichier Draco à charger. Dans ce cas, il s'agit de "bunny.drc" de l'étape précédente.
// Download and decode the Draco encoded geometry.
function downloadEncodedMesh(filename) {
// Download the encoded file.
const xhr = new XMLHttpRequest();
xhr.open("GET", filename, true);
xhr.responseType = "arraybuffer";
xhr.onload = function(event) {
const arrayBuffer = xhr.response;
if (arrayBuffer) {
const byteArray = new Uint8Array(arrayBuffer);
decodeMesh(byteArray);
}
};
xhr.send(null);
}
- Appelez la fonction "createDracoDecoderModule" pour créer le module de décodage Draco, qui appellera la fonction "downloadEncodedMesh" pour télécharger le fichier Draco encodé, qui appellera la fonction "decodeMesh" pour décoder le maillage Draco encodé.
// Create the Draco decoder module.
createDracoDecoderModule();
</script>
</head>
<body>
</body>
</html>
- Enregistrez ce fichier sous le nom "DracoDecode.html".
- Démarrez le serveur Web Python. Dans le terminal, saisissez :
python -m SimpleHTTPServer
- Ouvrez localhost:8000/DracoDecode.html dans Chrome. Une boîte de message d'alerte devrait s'afficher avec le nombre de points (Nombre de points = 34834) décodés à partir du modèle.
6. Afficher un fichier Draco avec three.js
Maintenant que nous savons comment décoder un fichier Draco à l'aide de WASM, nous allons utiliser un lecteur 3D Web populaire : three.js. Comme dans l'exemple précédent, nous allons commencer par copier et coller les sections de code suivantes dans l'éditeur de texte.
- Commencer avec un fichier HTML de base
<!DOCTYPE html>
<html>
<head>
<title>Codelab - Draco three.js Render</title>
- Ajoutez du code pour charger three.js et le chargeur Draco three.js.
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@v0.162.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@v0.162.0/examples/jsm/"
}
}
</script>
- Configurez le chemin d'accès au décodeur Draco.
<script type="module">
// import three.js and DRACOLoader.
import * as THREE from 'three';
import {DRACOLoader} from 'three/addons/loaders/DRACOLoader.js'
// three.js globals.
var camera, scene, renderer;
// Create the Draco loader.
var dracoLoader = new DRACOLoader();
// Specify path to a folder containing WASM/JS decoding libraries.
// It is recommended to always pull your Draco JavaScript and WASM decoders
// from the below URL. Users will benefit from having the Draco decoder in
// cache as more sites start using the static URL.
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.1/');
- Ajoutez le code de rendu three.js.
function initThreejs() {
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 0.1, 15 );
camera.position.set( 3, 0.25, 3 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x443333 );
scene.fog = new THREE.Fog( 0x443333, 1, 4 );
// Ground
var plane = new THREE.Mesh(
new THREE.PlaneGeometry( 8, 8 ),
new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } )
);
plane.rotation.x = - Math.PI / 2;
plane.position.y = 0.03;
plane.receiveShadow = true;
scene.add(plane);
// Lights
var light = new THREE.HemisphereLight( 0x443333, 0x111122 );
scene.add( light );
var light = new THREE.SpotLight();
light.angle = Math.PI / 16;
light.penumbra = 0.5;
light.castShadow = true;
light.position.set( - 1, 1, 1 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
const container = document.getElementById('container');
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
render();
requestAnimationFrame( animate );
}
function render() {
var timer = Date.now() * 0.0003;
camera.position.x = Math.sin( timer ) * 0.5;
camera.position.z = Math.cos( timer ) * 0.5;
camera.lookAt( new THREE.Vector3( 0, 0.1, 0 ) );
renderer.render( scene, camera );
}
- Ajoutez le code de chargement et de décodage Draco.
function loadDracoMesh(dracoFile) {
dracoLoader.load(dracoFile, function ( geometry ) {
geometry.computeVertexNormals();
var material = new THREE.MeshStandardMaterial( { vertexColors: THREE.VertexColors } );
var mesh = new THREE.Mesh( geometry, material );
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add( mesh );
} );
}
- Ajoutez du code pour charger le fichier.
window.onload = function() {
initThreejs();
animate();
loadDracoMesh('bunny.drc');
}
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
- Enregistrez ce fichier sous le nom "DracoRender.html".
- Si nécessaire, redémarrez le serveur Web.
python -m SimpleHTTPServer
- Ouvrez localhost:8000/DracoRender.html dans Chrome. Votre fichier Draco devrait maintenant s'afficher dans le navigateur.
7. Essayer différents paramètres d'encodage
L'encodeur Draco permet de définir de nombreux paramètres différents qui ont un impact sur la taille du fichier compressé et la qualité visuelle du code. Essayez d'exécuter les commandes suivantes dans la ligne de commande et d'observer les résultats.
- La commande suivante quantifie les positions du modèle à l'aide de 12 bits (la valeur par défaut est 11).
./draco_encoder -i ../testdata/bun_zipper.ply -o out12.drc -qp 12
- Notez la taille du fichier out12.drc par rapport à celle du fichier bunny.drc de la section précédente. L'utilisation de plus de bits de quantification peut augmenter la taille du fichier compressé.
3.La commande suivante quantifie les positions du modèle à l'aide de 6 bits.
./draco_encoder -i ../testdata/bun_zipper.ply -o out6.drc -qp 6
- Notez la taille du fichier out6.drc par rapport au fichier bunny.drc de la section précédente. L'utilisation d'un nombre de bits de quantification inférieur peut réduire la taille du fichier compressé.
- Les paramètres suivants ont une incidence sur les niveaux de compression du modèle. L'indicateur "cl" vous permet de régler votre compression de 1 (taux de compression le plus faible) à 10 (taux le plus élevé).
./draco_encoder -i ../testdata/bun_zipper.ply -o outLow.drc -cl 1
./draco_encoder -i ../testdata/bun_zipper.ply -o outHigh.drc -cl 10
Notez la sortie de l'encodeur Draco. Vous pouvez constater qu'il existe un compromis entre le temps nécessaire à la compression aux niveaux de compression les plus élevés et les économies en bits. Le paramètre approprié pour votre application dépendra des exigences de timing et de taille au moment de l'encodage.
8. Félicitations
Vous avez terminé l'atelier de programmation sur la compression de maillage Draco et avez exploré de nombreuses fonctionnalités clés de Draco.
Nous espérons que vous comprenez mieux comment Draco peut vous aider à réduire la taille de vos composants 3D et à les transmettre plus efficacement sur le Web. Pour en savoir plus sur Draco et obtenir la dernière bibliothèque, consultez GitHub.