1. Übersicht
3D-Grafiken sind ein grundlegender Bestandteil vieler Anwendungen, darunter Spiele, Design und Datenvisualisierung. Da sich Grafikprozessoren und Erstellungstools ständig verbessern, werden größere und komplexere 3D-Modelle immer häufiger eingesetzt und tragen zu neuen Anwendungen in immersiver Virtual Reality (VR) und Augmented Reality (AR) bei. Aufgrund dieser erhöhten Modellkomplexität müssen die Speicher- und Bandbreitenanforderungen mit der Explosion von 3D-Daten Schritt halten.
Mit Draco können Anwendungen, die 3D-Grafiken verwenden, deutlich kleiner sein, ohne dass die visuelle Qualität beeinträchtigt wird. Für Nutzer bedeutet das, dass Apps jetzt schneller heruntergeladen werden können, 3D-Grafiken im Browser schneller geladen werden und VR- und AR-Szenen jetzt mit einem Bruchteil der Bandbreite übertragen, schnell gerendert und fantastisch aussehen können.
Was ist Draco?
Draco ist eine Bibliothek zum Komprimieren und Dekomprimieren von 3D-geometrischen Meshes und Punktwolken. Es soll die Speicherung und Übertragung von 3D-Grafiken verbessern.
Draco wurde für Komprimierungseffizienz und Geschwindigkeit entwickelt und erstellt. Der Code unterstützt das Komprimieren von Punkten, Verbindungsinformationen, Texturkoordinaten, Farbinformationen, Normalen und allen anderen generischen Attributen, die mit der Geometrie verknüpft sind. Draco wird als C++-Quellcode veröffentlicht, mit dem 3D-Grafiken komprimiert werden können. Außerdem sind C++- und JavaScript-Decoder für die codierten Daten verfügbar.
Lerninhalte
- 3D-Modell mit Draco komprimieren
- So verwenden Sie verschiedene Komprimierungsmodelle und wie sie sich auf die Modellqualität und -größe auswirken
- 3D-Modelle im Web ansehen
Voraussetzungen
- Eine aktuelle Version von Chrome
- Der Beispielcode
- Texteditor
- Python
- cmake
2. Einrichtung
Klonen Sie das GitHub-Repository mit dieser Befehlszeile:
git clone https://github.com/google/draco
Rufen Sie das Draco-Stammverzeichnis auf.
cd draco
3. Encoder erstellen
Bevor wir mit der Draco-Codierung und -Decodierung beginnen, erstellen wir zuerst die Apps.
Encoder erstellen
- Führen Sie „cmake“ in einem Verzeichnis aus, in dem Sie Build-Dateien generieren möchten, und übergeben Sie den Pfad zu Ihrem Draco-Repository.
mkdir build
cd build
cmake ../
make
4. Erstes 3D-Asset codieren
draco_encoder liest OBJ- oder PLY-Dateien als Eingabe und gibt Draco-codierte Dateien aus. Wir haben das Stanford Bunny-Mesh zum Testen hinzugefügt. Die grundlegende Befehlszeile sieht so aus:
./draco_encoder -i ../testdata/bun_zipper.ply -o bunny.drc
Sie können sich jetzt die Größe der Ausgabedatei ansehen und mit der ursprünglichen PLY-Datei vergleichen. Die komprimierte Datei sollte viel kleiner als die Originaldatei sein.
Hinweis: Die komprimierte Größe kann je nach Komprimierungsoptionen variieren.
5. Draco-Datei im Browser decodieren
An dieser Stelle beginnen wir mit einer einfachen Webseite zum Decodieren von Draco-Dateien. Kopieren Sie zuerst die folgenden Codeabschnitte und fügen Sie sie in den Texteditor ein.
- Beginnen Sie mit einer einfachen HTML-Datei.
<!DOCTYPE html>
<html>
<head>
<title>Codelab - Draco Decoder</title>
- Mit dem folgenden Code-Snippet wird der Draco WASM-Decoder geladen.
<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>
- Fügen Sie als Nächstes diese Funktion hinzu, mit der ein Draco-Decodermodul erstellt wird. Das Erstellen des Decodermoduls erfolgt asynchron. Sie müssen also warten, bis der Callback aufgerufen wird, bevor Sie das Modul verwenden können.
<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);
}
- Fügen Sie die Funktion zum Decodieren eines Draco-codierten Mesh hinzu.
// 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);
}
- Nachdem wir nun die Draco-Decodierungsfunktion haben, fügen wir eine Funktion zum Herunterladen eines Draco-codierten Mesh hinzu. Die Funktion „downloadEncodedMesh“ akzeptiert einen Parameter für die zu ladende Draco-Datei. In diesem Fall ist es „bunny.drc“ aus der vorherigen Phase.
// 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);
}
- Rufen Sie die Funktion „createDracoDecoderModule“ auf, um das Draco-Decodermodul zu erstellen. Dadurch wird die Funktion „downloadEncodedMesh“ aufgerufen, um die codierte Draco-Datei herunterzuladen. Dadurch wird die Funktion „decodeMesh“ aufgerufen, um das codierte Draco-Mesh zu decodieren.
// Create the Draco decoder module.
createDracoDecoderModule();
</script>
</head>
<body>
</body>
</html>
- Speichern Sie diese Datei als „DracoDecode.html“.
- Starten Sie den Python-Webserver. Geben Sie im Terminal Folgendes ein:
python -m SimpleHTTPServer
- Öffnen Sie localhost:8000/DracoDecode.html in Chrome. Es sollte ein Warnmeldungsfeld mit der Anzahl der Punkte (Num points = 34834) angezeigt werden, die aus dem Modell decodiert wurden.
6. Draco-Datei mit three.js rendern
Nachdem wir nun wissen, wie wir eine Draco-Datei mit WASM decodieren, verwenden wir einen beliebten 3D-Web-Viewer: three.js. Wie im vorherigen Beispiel kopieren wir zuerst die folgenden Codeabschnitte und fügen sie in den Texteditor ein.
- Mit einer einfachen HTML-Datei beginnen
<!DOCTYPE html>
<html>
<head>
<title>Codelab - Draco three.js Render</title>
- Fügen Sie Code hinzu, um three.js und den Draco three.js-Loader zu laden.
<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>
- Richten Sie den Draco-Decoderpfad ein.
<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/');
- Fügen Sie den Rendering-Code für three.js hinzu.
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 );
}
- Fügen Sie Code zum Laden und Decodieren von Draco hinzu.
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 );
} );
}
- Fügen Sie Code zum Laden der Datei hinzu.
window.onload = function() {
initThreejs();
animate();
loadDracoMesh('bunny.drc');
}
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
- Speichern Sie diese Datei als „DracoRender.html“.
- Starten Sie den Webserver bei Bedarf neu.
python -m SimpleHTTPServer
- Öffnen Sie localhost:8000/DracoRender.html in Chrome. Ihre Draco-Datei sollte jetzt im Browser gerendert werden.
7. Andere Codierungsparameter ausprobieren
Der Draco-Encoder bietet viele verschiedene Parameter, die sich auf die Größe der komprimierten Datei und die visuelle Qualität des Codes auswirken. Führen Sie die nächsten Befehle in der Befehlszeile aus und sehen Sie sich die Ergebnisse an.
- Mit dem folgenden Befehl werden die Positionen des Modells mit 12 Bit quantisiert (Standardwert ist 11).
./draco_encoder -i ../testdata/bun_zipper.ply -o out12.drc -qp 12
- Vergleichen Sie die Größe von „out12.drc“ mit der Datei „bunny.drc“ im vorherigen Abschnitt. Wenn Sie mehr Quantisierungsbits verwenden, kann die Größe der komprimierten Datei zunehmen.
3.Mit dem folgenden Befehl werden die Positionen des Modells mit 6 Bit quantisiert.
./draco_encoder -i ../testdata/bun_zipper.ply -o out6.drc -qp 6
- Vergleichen Sie die Größe von „out6.drc“ mit der Datei „bunny.drc“ im vorherigen Abschnitt. Wenn Sie weniger Quantisierungsbits verwenden, kann die Größe der komprimierten Datei reduziert werden.
- Die folgenden Parameter wirken sich auf die Komprimierungsstufen des Modells aus. Mit dem Flag „cl“ können Sie die Komprimierung zwischen 1 (niedrigstes Komprimierungsverhältnis) und 10 (höchstes) anpassen.
./draco_encoder -i ../testdata/bun_zipper.ply -o outLow.drc -cl 1
./draco_encoder -i ../testdata/bun_zipper.ply -o outHigh.drc -cl 10
Sehen Sie sich die Ausgabe des Draco-Encoders an. Sie sehen, dass es bei den höchsten Komprimierungsstufen einen Kompromiss zwischen der für die Komprimierung erforderlichen Zeit und den Einsparungen bei den Bits gibt. Der richtige Parameter für Ihre Anwendung hängt von den Zeit- und Größenanforderungen zur Codierungszeit ab.
8. Glückwunsch
Sie haben das Draco-Mesh-Komprimierungs-Code-Lab abgeschlossen und viele wichtige Funktionen von Draco kennengelernt.
Wir hoffen, dass Sie jetzt wissen, wie Draco Ihnen helfen kann, Ihre 3D-Assets zu verkleinern und effizienter über das Web zu übertragen. Weitere Informationen zu Draco und die aktuelle Bibliothek finden Sie auf GitHub.