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.
The convergence of AI and XR is not a future trend — it's happening now. Vision-language models (VLMs) can see what your headset sees. LLMs can power NPCs that hold real conversations. Neural networks can reconstruct 3D scenes from sparse camera input.
This article catalogs production-ready integration patterns you can build today with WebXR, browser-based ML, and self-hosted AI infrastructure.
Your XR app needs to understand the physical world — not just track planes and anchors, but recognize objects, read text, identify hazards, or describe a scene to a visually impaired user.
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]}, ...]
}
| Factor | On-device (WebNN/WASM) | Cloud API |
|---|---|---|
| Latency | 50-200ms | 500-3000ms |
| Privacy | Full — data never leaves | Requires trust |
| Model quality | Smaller, less capable | Frontier models |
| Cost | Fixed (compute) | Per-token |
| Offline capable | Yes | No |
Recommendation: Use on-device for real-time spatial understanding (object detection, plane classification) and cloud VLMs for complex queries ("what does this sign say?" or "find my keys").
Aria glasses use on-device SLAM + cloud VLM for contextual AI assistance. The same pattern works with Meta Quest Pro, Apple Vision Pro, or any WebXR-capable device with a camera pass-through.
Virtual assistants today live in a chat window. In XR, they should live in the space — anchored to a real table, pointing at real objects, aware of their physical surroundings.
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);
Spatial memory — the assistant should remember where objects are between sessions. Use a spatial database (e.g., PostgreSQL + PostGIS, or a lightweight R-tree) to persist anchor positions and their semantic labels.
Gaze awareness — track what the user is looking at using WebXR gaze or hand tracking. Pass the gazed-at object into the LLM context so the assistant can answer "what's that?" without explicit pointing.
Turn-taking — use WebXR microphone access with voice activity detection (VAD). Don't make users press a button to speak in VR.
// 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);
}
High-quality 3D reconstruction from sparse camera input enables persistent AR — objects stay in the same place even when you leave the room and come back.
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);
}
For production use, run reconstruction on your own GPU infrastructure:
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]
Typing is terrible in VR. A voice interface with NLP parsing is the natural input modality for immersive environments.
// 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;
}
};
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.
<!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>
To run this yourself:
/api/ai/detect-objects — or let the mock runTo build on these patterns in your own projects:
XR + AI is the most sensor-rich computing paradigm we've built. Cameras see everything. Microphones hear everything. Models run everywhere.