Back openDesk Edu for a sovereign, open-source education â every vote counts.
Vote nowSave products you love by clicking the heart icon.
WebGPU hat den Baseline-Status erreicht, Safari hat endlich WebXR implementiert, KI-gestĂŒtzte XR-Entwicklung von Meta und Google ist angekommen und die Adaption ist um 40 % gestiegen. Ein nĂŒchterner Blick auf das immersive Web-Ăkosystem Mitte 2026.
WebGPU hit Baseline, Safari finally shipped WebXR, AI-assisted XR development landed from Meta and Google, and adoption surged 40%. A no-hype look at the immersive web ecosystem in mid-2026.
Die Konvergenz von AI und XR ist kein zukĂŒnftiger Trend â sie findet bereits jetzt statt. Vision-Language-Modelle (VLMs) können sehen, was Ihr Headset sieht. LLMs können NPCs antreiben, die echte GesprĂ€che fĂŒhren. Neuronale Netze können 3D-Szenen aus spĂ€rlichen Kamera-Inputs rekonstruieren.
Dieser Artikel katalogisiert einsatzbereite Integrationsmuster, die Sie heute mit WebXR, browserbasiertem ML und selbstgehosteter AI-Infrastruktur implementieren können.
Ihre XR-App muss die physische Welt verstehen â nicht nur Ebenen und Anker tracken, sondern Objekte erkennen, Texte lesen, Gefahren identifizieren oder eine Szene fĂŒr einen sehbehinderten Nutzer beschreiben.
WebXR Camera â Canvas Capture â VLM (API or local) â JSON structured output â XR overlay
// Capture the WebXR camera feed as a frame
function captureFrame(xrFrame, referenceSpace, gl) {
const viewerPose = xrFrame.getViewerPose(referenceSpace);
if (!viewerPose) return null;
const canvas = document.createElement("canvas");
canvas.width = gl.drawingBufferWidth;
canvas.height = gl.drawingBufferHeight;
// Read back WebXR layer pixels (requires WEBGL_draw_pixels or copyTexImage2D)
// This is simplified â production code uses XRWebGLBinding or WebGPU
const pixels = new Uint8Array(canvas.width * canvas.height * 4);
gl.readPixels(0, 0, canvas.width, canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
// Send to VLM (e.g., Gemini Pro Vision, Claude 3.5 Sonnet, or local Florence-2)
return describeScene(pixels, canvas.width, canvas.height);
}
async function describeScene(pixels, width, height) {
const response = await fetch("/api/ai/describe-scene", {
method: "POST",
body: JSON.stringify({
image: arrayBufferToBase64(pixels),
width,
height,
prompt: "List all objects, their positions, and any readable text in this scene.",
}),
});
return response.json(); // e.g., [{object: "chair", position: [1.2, 0, -0.5]}, ...]
}
| Faktor | On-device (WebNN/WASM) | Cloud API |
|---|---|---|
| Latenz | 50-200ms | 500-3000ms |
| Datenschutz | VollstĂ€ndig â Daten verlassen das GerĂ€t nicht | Erfordert Vertrauen |
| ModellqualitÀt | Kleiner, weniger leistungsfÀhig | Frontier-Modelle |
| Kosten | Fix (Rechenleistung) | Pro Token |
| Offline-fÀhig | Ja | Nein |
Empfehlung: Nutzen Sie On-Device fĂŒr rĂ€umliches VerstĂ€ndnis in Echtzeit (Objekterkennung, Ebenenklassifizierung) und Cloud-VLMs fĂŒr komplexe Abfragen (âWas steht auf diesem Schild?â oder âFinde meine SchlĂŒsselâ).
Die Aria-Brille nutzt On-Device SLAM + Cloud-VLM fĂŒr kontextuelle AI-UnterstĂŒtzung. Dasselbe Muster funktioniert mit der Meta Quest Pro, Apple Vision Pro oder jedem WebXR-fĂ€higen GerĂ€t mit Kamera-Pass-through.
Virtuelle Assistenten existieren heute in einem Chat-Fenster. In XR sollten sie im Raum existieren â verankert an einem echten Tisch, auf echte Objekte zeigend und sich ihrer physischen Umgebung bewusst.
Spatial Anchor â LLM Context (scene description + user query) â LLM Response â TTS + Spatial Audio + Animated Avatar
// Create an AI assistant anchored to a real-world location
const assistantAnchor = await xrFrame.createAnchor(
new XRRigidTransform(
{ x: 1.5, y: 1.2, z: -2.0 }, // position in room space
{ x: 0, y: 0, z: 0, w: 1 }, // facing user
),
referenceSpace,
);
// Build context from the current scene understanding
const sceneContext = await getCurrentSceneDescription();
const userQuery = "What's that device on my desk?";
const response = await fetch("/api/ai/assistant", {
method: "POST",
body: JSON.stringify({
query: userQuery,
context: {
scene: sceneContext,
user_position: userPose.transform.position,
assistant_position: assistantAnchor.position,
conversation_history: recentMessages,
},
}),
});
// Render the assistant's response as speech + text
speakText(response.answer);
showSpeechBubble(response.answer, assistantAnchor);
RĂ€umliches GedĂ€chtnis (Spatial Memory) â der Assistent sollte sich zwischen den Sitzungen merken, wo sich Objekte befinden. Verwenden Sie eine rĂ€umliche Datenbank (z. B. PostgreSQL + PostGIS oder einen leichtgewichtigen R-Tree), um Ankerpositionen und deren semantische Bezeichnungen dauerhaft zu speichern.
Blickbewusstsein (Gaze Awareness) â tracken Sie, was der Nutzer ansieht, mittels WebXR Gaze oder Hand-Tracking. Ăbergeben Sie das betrachtete Objekt in den LLM-Kontext, sodass der Assistent auf die Frage âWas ist das?â antworten kann, ohne dass explizit darauf gezeigt werden muss.
Turn-taking â nutzen Sie den WebXR-Mikrofonzugriff mit Voice Activity Detection (VAD). Zwingen Sie die Nutzer in VR nicht dazu, eine Taste zum Sprechen zu drĂŒcken.
// Gaze-aware query
function getGazedObject(frame, referenceSpace) {
const gazeRay =
frame.getJointPose?.(xrFrame, "gaze") || frame.getViewerPose(referenceSpace)?.transform;
// Raycast into your spatial scene graph
return scene.raycast(gazeRay);
}
Hochwertige 3D-Rekonstruktionen aus spĂ€rlichen Kamera-Inputs ermöglichen persistente AR â Objekte bleiben an derselben Stelle, selbst wenn man den Raum verlĂ€sst und spĂ€ter zurĂŒckkehrt.
async function reconstructScene(videoFrames) {
// Upload frames to reconstruction server (or run on-device with WebNN)
const scene = await fetch("/api/xr/reconstruct", {
method: "POST",
body: videoFrames, // MP4 or frame sequence
});
// Receive back a 3D Gaussian splat scene representation
const splatData = await scene.arrayBuffer();
// Render with WebGPU
const renderer = new GaussianSplatRenderer(device, context);
renderer.uploadSplats(splatData);
renderer.render(viewMatrix, projectionMatrix);
}
FĂŒr den produktiven Einsatz fĂŒhren Sie die Rekonstruktion auf Ihrer eigenen GPU-Infrastruktur aus:
services:
gaussian-splatting:
image: ghcr.io/graphdeco-inria/gaussian-splatting:latest
ports:
- "7860:7860"
volumes:
- ./output:/output
- ./input:/input
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
Tippen ist in VR extrem mĂŒhsam. Ein Voice-Interface mit NLP-Parsing ist die natĂŒrliche EingabemodalitĂ€t fĂŒr immersive Umgebungen.
// Web speech API + LLM intent parsing
const recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
recognition.onresult = async (event) => {
const transcript = event.results[event.results.length - 1][0].transcript;
// Parse intent with a lightweight NLU model or LLM
const intent = await fetch("/api/ai/parse-intent", {
method: "POST",
body: JSON.stringify({ text: transcript, context: currentSpatialContext }),
});
// Execute spatial commands
switch (intent.action) {
case "place_object":
placeObject(intent.object, userGazePosition);
break;
case "resize":
resizeSelectedObject(intent.scale);
break;
case "query":
showInformationPanel(intent.query, userGazePosition);
break;
}
};
## Complete Demo: Spatial Object Labeler
Below is a self-contained HTML page that combines WebXR, on-device object detection, and LLM-powered labeling. It captures the XR camera frame, runs a local ML model via WebNN (or falls back to a mock), and renders labeled bounding boxes in 3D space.
```html
<!DOCTYPE html>
<html>
<head>
<title>Spatial Object Labeler â XR + AI Demo</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.min.js"></script>
</head>
<body>
<script>
// âââ WebXR Setup âââââââââââââââââââââââââââââââââââââ
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.xr.enabled = true;
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 100);
// âââ AI Integration ââââââââââââââââââââââââââââââââââ
async function detectObjects(frame, referenceSpace) {
const viewerPose = frame.getViewerPose(referenceSpace);
if (!viewerPose) return [];
// Capture a canvas frame (simplified â production uses XRWebGLBinding)
const canvas = document.createElement('canvas');
canvas.width = 640; canvas.height = 480;
// Mock detections for demo. In production, replace with a call to
// a self-hosted VLM endpoint (e.g., Ollama + LLaVA, vLLM + Pixtral):
//
// const response = await fetch('/api/ai/detect-objects', {
// method: 'POST',
// body: JSON.stringify({ image: canvas.toDataURL('image/jpeg', 0.8) })
// });
// return await response.json();
return [
{ label: 'chair', confidence: 0.92, x: 0.5, y: -0.3, z: -1.2 },
{ label: 'table', confidence: 0.88, x: 0.8, y: 0.0, z: -1.5 },
{ label: 'laptop', confidence: 0.76, x: 0.3, y: 0.4, z: -0.8 }
];
}
// âââ Render Detections âââââââââââââââââââââââââââââââ
function renderDetections(objects) {
// Clear previous labels
scene.children.filter(c => c.userData?.isLabel).forEach(c => scene.remove(c));
for (const obj of objects) {
const geometry = new THREE.SphereGeometry(0.05, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: obj.confidence > 0.8 ? 0x00ff00 : 0xffaa00
});
const sphere = new THREE.Mesh(geometry, material);
sphere.position.set(obj.x, obj.y, obj.z);
sphere.userData.isLabel = true;
scene.add(sphere);
// Text label (using sprite)
const canvas2 = document.createElement('canvas');
canvas2.width = 256; canvas2.height = 64;
const ctx = canvas2.getContext('2d');
ctx.fillStyle = 'rgba(0,0,0,0.7)';
ctx.fillRect(0, 0, 256, 64);
ctx.fillStyle = 'white';
ctx.font = '24px monospace';
ctx.fillText(`${obj.label} (${(obj.confidence*100).toFixed(0)}%)`, 16, 44);
const texture = new THREE.CanvasTexture(canvas2);
const spriteMat = new THREE.SpriteMaterial({ map: texture });
const sprite = new THREE.Sprite(spriteMat);
sprite.position.set(obj.x, obj.y + 0.15, obj.z);
sprite.scale.set(0.4, 0.1, 1);
sprite.userData.isLabel = true;
scene.add(sprite);
}
}
// âââ Session Loop ââââââââââââââââââââââââââââââââââââ
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['local']
});
renderer.xr.setSession(session);
renderer.setAnimationLoop((timestamp, frame) => {
if (frame) {
const objects = await detectObjects(frame, renderer.xr.getReferenceSpace());
renderDetections(objects);
}
renderer.render(scene, camera);
});
</script>
</body>
</html>
Um dies selbst auszufĂŒhren:
/api/ai/detect-objects â oder lassen Sie den Mock-Modus laufenUm diese Muster in Ihren eigenen Projekten zu nutzen:
XR + AI ist das sensorreichste Computing-Paradigma, das wir bisher entwickelt haben. Kameras sehen alles. Mikrofone hören alles. Modelle laufen ĂŒberall.