Three.js Performance optimieren.
Deine Szene läuft auf dem Rechner flüssig und auf dem Handy wie eine Diashow? Hier sind die Maßnahmen, die in der Praxis am meisten bringen — sortiert nach Wirkung, mit Code und einer Checkliste zum Abhaken.
Die größten Hebel sind fast immer dieselben: Pixel-Ratio begrenzen, Draw Calls senken (zusammenfassen oder Instancing), Texturen verkleinern und nur rendern, wenn sich etwas ändert. Erst messen, dann optimieren — sonst optimiert man das Falsche.
Schritt 0: Messen.
Bevor irgendetwas optimiert wird: herausfinden, wo die Zeit verloren geht. renderer.info zeigt, wie viele Draw Calls, Dreiecke und Texturen pro Bild anfallen. Die Performance-Ansicht der Browser-Entwicklertools zeigt, ob JavaScript oder die Grafikkarte der Engpass ist.
// Alle 2 Sekunden die wichtigsten Werte in die Konsole
setInterval(() => {
const i = renderer.info;
console.table({
drawCalls: i.render.calls,
dreiecke: i.render.triangles,
geometrien: i.memory.geometries,
texturen: i.memory.textures
});
}, 2000);Faustregel für Mobilgeräte: unter etwa 100 Draw Calls bleiben. Steigen Geometrien und Texturen mit der Zeit immer weiter, liegt ein Speicherleck vor.
1. Pixel-Ratio begrenzen.
Moderne Smartphones haben eine Pixeldichte von 3 oder mehr. Rendert Three.js mit voller Dichte, berechnet die Grafikkarte neunmal so viele Pixel wie bei Dichte 1. Der Unterschied zwischen 2 und 3 ist mit bloßem Auge kaum zu sehen, in der Leistung aber enorm: renderer.setPixelRatio(Math.min(devicePixelRatio, 2)). Das ist die wirkungsvollste einzelne Zeile.
2. Draw Calls senken.
Jedes einzelne Mesh ist mindestens ein Aufruf an die Grafikkarte. Hunderte Schrauben als einzelne Objekte töten jede Szene. Zwei Lösungen:
const geo = new THREE.CylinderGeometry(0.05, 0.05, 0.3, 8);
const mat = new THREE.MeshStandardMaterial({ color: 0x888888 });
const schrauben = new THREE.InstancedMesh(geo, mat, 1000);
const m = new THREE.Matrix4();
for (let i = 0; i < 1000; i++) {
m.setPosition(Math.random() * 10, 0, Math.random() * 10);
schrauben.setMatrixAt(i, m);
}
schrauben.instanceMatrix.needsUpdate = true;
scene.add(schrauben);Für gleiche Objekte an vielen Stellen ist InstancedMesh ideal. Unterschiedliche, statische Teile mit gleichem Material lassen sich stattdessen mit mergeGeometries aus BufferGeometryUtils zusammenfassen.
3. Texturen verkleinern.
Eine 4K-Textur belegt unkomprimiert rund 85 MB Grafikspeicher — egal, wie klein die Datei auf dem Server ist, denn im Speicher wird sie entpackt. Für die meisten Objekte reichen 1K oder 2K. Das Format KTX2 mit Basis-Kompression bleibt auch im Grafikspeicher komprimiert und ist auf Mobilgeräten oft der Unterschied zwischen läuft und stürzt ab.
4. Nur rendern, wenn nötig.
Eine Szene, die sich nicht bewegt, muss nicht 60-mal pro Sekunde neu gezeichnet werden. Rendern nur bei Interaktion oder Veränderung spart Akku und hält Geräte kühl. Ebenso wichtig: das Rendern stoppen, wenn die Szene aus dem sichtbaren Bereich gescrollt ist.
5. Speicher freigeben.
Three.js räumt Geometrien, Materialien und Texturen nicht automatisch auf. Wird eine Szene ausgetauscht, ohne dispose() aufzurufen, wächst der Speicher bei jedem Wechsel — bis der Browser-Tab abstürzt. Besonders tückisch in Konfiguratoren, in denen Modelle ständig gewechselt werden.
6. Schatten und Licht überdenken.
Echtzeit-Schatten verdoppeln oft den Rechenaufwand. Für statische Szenen wirkt vorberechnetes Licht in der Textur meist sogar besser. Wenn Echtzeit-Schatten nötig sind: nur für wenige Objekte und mit kleiner Schattenkarte.
[ ] setPixelRatio auf maximal 2 begrenzt
[ ] renderer.info geprüft: Draw Calls unter ca. 100 (mobil)
[ ] gleiche Objekte als InstancedMesh
[ ] statische Teile mit gleichem Material zusammengefasst
[ ] Geometrie mit Draco komprimiert
[ ] Texturen maximal 2K, möglichst KTX2
[ ] Rendern pausiert, wenn Szene nicht sichtbar
[ ] dispose() beim Austausch von Modellen und Materialien
[ ] Echtzeit-Schatten nur, wo wirklich nötig
[ ] auf einem echten Mittelklasse-Smartphone getestetDer letzte Punkt ist der wichtigste. Entwickler-Rechner und Flaggschiff-Handys verzeihen alles — die Geräte deiner Besucher nicht.
Nicht glauben — ausprobieren.
Alle Demos laufen live im Browser, auch auf dem Smartphone.
FAQ — Three.js Performance optimieren.
Warum ruckelt meine Three.js-Szene auf dem Smartphone?
Die häufigsten Ursachen sind eine unbegrenzte Pixeldichte, zu viele Draw Calls durch einzelne Objekte, zu große Texturen und Echtzeit-Schatten. Allein das Begrenzen der Pixel-Ratio auf 2 bringt auf modernen Smartphones oft einen deutlichen Leistungsgewinn.
Wie viele Draw Calls sind zu viele?
Als grobe Orientierung sollten Szenen für Mobilgeräte unter etwa 100 Draw Calls bleiben. Auf Desktop-Rechnern sind mehrere hundert oft unproblematisch. Den aktuellen Wert zeigt renderer.info.render.calls.
Was ist Instancing in Three.js?
Instancing zeichnet viele gleiche Objekte mit einem einzigen Draw Call. Statt tausend einzelner Meshes wird ein InstancedMesh angelegt, das für jede Kopie nur Position, Drehung und Größe speichert. Das ist ideal für Schrauben, Bäume, Partikel oder andere wiederholte Objekte.
Warum stürzt mein Browser-Tab nach einiger Zeit ab?
Meist liegt ein Speicherleck vor. Three.js gibt Geometrien, Materialien und Texturen nicht automatisch frei. Werden Modelle ausgetauscht, ohne dispose() aufzurufen, wächst der Speicherbedarf mit jedem Wechsel, bis der Browser den Tab beendet.
Welches Texturformat ist für Three.js am besten?
Für Mobilgeräte ist KTX2 mit Basis-Kompression meist die beste Wahl, weil die Textur auch im Grafikspeicher komprimiert bleibt. WebP oder JPEG sind zwar auf dem Server klein, werden im Speicher aber vollständig entpackt.
Das bin ich – rechts im BildErzähl mir, was du zeigen willst.
Ich sage dir ehrlich, ob sich 3D für dein Vorhaben lohnt — und wenn nicht, was stattdessen mehr bringt.
Antwort meist innerhalb von 24 Stunden · hallo@manuelkillert.de

