Back openDesk Edu for a sovereign, open-source education — every vote counts.
Vote nowSave products you love by clicking the heart icon.
Eine umfassende Einführung in die Virtual Reality, die die Grundlagen der Computergrafik, stereoskopisches Sehen, die Geschichte von VR, Gerätekategorien, Motion Tracking und das Reality-Virtuality-Kontinuum abdeckt.
Optimierung der KI-Inferenz für XR-Geräte — Modellquantisierung, NPU-Beschleunigung, hierarchisches Serving, Bandbreitenoptimierung für Echtzeit-Rendering mit 60 fps.
Die Performance entscheidet über Erfolg oder Misserfolg von XR-Erlebnissen. Ein ausgelassener Frame in VR führt zu Motion Sickness. Hier erfahren Sie, wie Sie Three.js für konsistente 60fps optimieren.
import Stats from 'three/examples/jsm/libs/stats.module.js';
const stats = new Stats();
document.body.appendChild(stats.dom);
function animate() {
stats.begin();
// render
stats.end();
requestAnimationFrame(animate);
}
```text
### Render Info
```javascript
console.log(renderer.info);
// {
// memory: { geometries: 12, textures: 8 },
// render: { calls: 45, triangles: 15000, points: 0, lines: 0 }
// }
```text
## Geometrie-Optimierung
### Geometrien zusammenführen (Merge Geometries)
```javascript
import { mergeBufferGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
const geometries = [];
for (let i = 0; i < 1000; i++) {
const geo = new THREE.BoxGeometry(1, 1, 1);
geo.translate(Math.random() * 100, 0, Math.random() * 100);
geometries.push(geo);
}
const merged = mergeBufferGeometries(geometries);
const mesh = new THREE.Mesh(merged, material);
// 1000 draw calls → 1 draw call
```text
### InstancedMesh
Für wiederkehrende, identische Objekte:
```javascript
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial();
const count = 10000;
const mesh = new THREE.InstancedMesh(geometry, material, count);
const matrix = new THREE.Matrix4();
for (let i = 0; i < count; i++) {
matrix.setPosition(
Math.random() * 100 - 50,
Math.random() * 50,
Math.random() * 100 - 50
);
mesh.setMatrixAt(i, matrix);
}
mesh.instanceMatrix.needsUpdate = true;
scene.add(mesh);
```text
## Material-Optimierung
### Materialien teilen
```javascript
// Bad: 1000 materials
for (let i = 0; i < 1000; i++) {
const mat = new THREE.MeshStandardMaterial({ color: 0xff0000 });
}
// Good: 1 shared material
const sharedMat = new THREE.MeshStandardMaterial({ color: 0xff0000 });
```text
### Ressourcenschonende Materialien verwenden
```javascript
// Most expensive
MeshPhysicalMaterial
// Medium
MeshStandardMaterial
// Cheaper
MeshLambertMaterial
// Cheapest
MeshBasicMaterial
```text
## Textur-Optimierung
### Texturgröße
```javascript
// Power of 2 Größen für GPU-Effizienz
const loader = new THREE.TextureLoader();
const texture = loader.load('texture.jpg');
texture.encoding = THREE.sRGBEncoding;
// Große Texturen anpassen
if (texture.image.width > 1024) {
// Texturkompression verwenden (KTX2, Basis)
}
```
```text
### Texture Atlasing
Combine multiple textures into one:
```javascript
// Statt 10 Materialien mit 10 Texturen
// Verwenden Sie 1 Material mit 1 Atlas-Textur
// Passen Sie die UVs pro Objekt an
```text
## Level of Detail (LOD)
```javascript
const lod = new THREE.LOD();
const highPoly = createHighPolyMesh(); // 10.000 Dreiecke
const mediumPoly = createMediumPolyMesh(); // 1.000 Dreiecke
const lowPoly = createLowPolyMesh(); // 100 Dreiecke
lod.addLevel(highPoly, 0); // Anzeigen bei 0-10 Distanz
lod.addLevel(mediumPoly, 10); // Anzeigen bei 10-50 Distanz
lod.addLevel(lowPoly, 50); // Anzeigen bei 50+ Distanz
scene.add(lod);
```text
## Frustum Culling
Three.js does this automatically, but verify:
```javascript
// Prüfen, ob das Objekt sichtbar ist
const frustum = new THREE.Frustum();
const matrix = new THREE.Matrix4().multiplyMatrices(
camera.projectionMatrix,
camera.matrixWorldInverse
);
frustum.setFromProjectionMatrix(matrix);
if (frustum.intersectsObject(mesh)) {
// Objekt ist sichtbar
}
```text
## Memory Management
### Dispose Pattern
```javascript
function disposeObject(obj) {
if (obj.geometry) {
obj.geometry.dispose();
}
if (obj.material) {
if (Array.isArray(obj.material)) {
obj.material.forEach(m => disposeMaterial(m));
} else {
disposeMaterial(obj.material);
}
}
}
function disposeMaterial(mat) {
if (mat.map) mat.map.dispose();
if (mat.normalMap) mat.normalMap.dispose();
if (mat.roughnessMap) mat.roughnessMap.dispose();
mat.dispose();
}
```text
### Object Pooling
```javascript
class ObjectPool {
constructor(createFn, maxSize = 100) {
this.pool = [];
this.createFn = createFn;
this.maxSize = maxSize;
}
get() {
return this.pool.pop() | | this.createFn();
}
release(obj) {
if (this.pool.length < this.maxSize) {
obj.visible = false;
this.pool.push(obj);
} else {
disposeObject(obj);
}
}
}
```text
## Web Worker Offloading
Move heavy computation off the main thread:
```javascript
// worker.js
self.onmessage = (e) => {
const { positions, velocities } = e.data;
for (let i = 0; i < positions.length; i++) {
positions[i] += velocities[i];
}
self.postMessage({ positions });
};
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ positions, velocities });
worker.onmessage = (e) => {
geometry.attributes.position.array = e.data.positions;
geometry.attributes.position.needsUpdate = true;
};
```text
## Performance Targets
| Platform | Target FPS | Draw Calls | Triangles |
| ---------- | ------------ | ------------ | ----------- |
| Desktop | 60 | < 2000 | < 10M |
| Mobile | 60 | < 500 | < 1M |
| VR Standalone | 72 | < 300 | < 500K |
| Mobile VR | 72 | < 100 | < 200K |
## Conclusion
Optimization is iterative. Profile, identify bottlenecks, optimize the biggest gains first. Geometry merging and instancing give the biggest improvements for typical scenes.