Platforms

Optimizing 3D Assets for WebXR

Prepare GLB assets for browser AR and VR with stable stereo frame time, real-world scale, mobile memory, interaction proxies, and fallbacks.

WebXR puts browser 3D inside a strict real-time loop with head tracking, stereo views for immersive VR, and camera processing for mobile AR. A brief hitch that is tolerable in a product thumbnail can feel uncomfortable when it delays the world during head motion.

Optimize for sustained frame time, real-world scale, memory, and interaction—not only the GLB download.

Define the XR experience#

Record supported modes and devices:

  • immersive-vr, immersive-ar, or both;
  • inline non-XR fallback;
  • lowest standalone headset;
  • lowest phone and browser for AR;
  • target refresh rates;
  • maximum objects and lights;
  • placement and movement range;
  • hand, controller, gaze, or screen input;
  • required hit testing, anchors, planes, or depth features.

At 72 Hz, the frame interval is about 13.89 milliseconds. At 90 Hz, it is 11.11 milliseconds. Browser, application, tracking, and rendering share that deadline.

Test the exact runtime and device. WebXR features and graphics behavior vary, and emulation cannot reproduce thermal, camera, or tracking costs.

Set physical scale#

glTF uses meters. A chair intended to be 0.9 meters tall should enter AR at that scale. Scale mistakes damage placement credibility, locomotion, reach, and collision.

Verify dimensions against a known reference. Set origin and pivot for placement: floor-standing objects need a predictable base; wall objects need an attachment plane; handheld items need a useful grip.

Bounds drive framing, selection, and placement previews. Remove outlier vertices and hidden capture fragments. An outlier 100 meters away can make the object appear tiny.

Avoid applying an arbitrary viewer scale to every model. If the product permits user scaling, begin from truthful dimensions and label the interaction.

Budget stereo and high resolution#

Immersive VR renders view-dependent work for two eyes. Multiview support can reduce some CPU and vertex duplication, but fragment coverage, materials, shadows, and render targets remain substantial.

Headset framebuffers can exceed visible panel dimensions due to lens distortion and quality policy. Query the actual layer and renderer size. Do not estimate from a desktop canvas.

Profile:

  • CPU application and submission time;
  • GPU time by pass;
  • view count and drawing-buffer dimensions;
  • rendered vertices and fragments;
  • draw calls and material state;
  • shadow maps;
  • post-processing;
  • frame misses and reprojection;
  • sustained behavior after 15 minutes.

A scene passing at 60 Hz on a monitor can fail at 90 Hz stereo.

Build a fast placement asset#

For AR, the camera and tracking system already consume device resources. Show a lightweight placement preview before full inspection detail.

A staged flow can load:

  1. poster or outline immediately;
  2. 200 KB–500 KB placement LOD;
  3. interaction-quality model after placement;
  4. close-detail textures on inspection intent.

The numbers are illustrative. Ensure every stage has stable bounds and pivot. Do not make the object jump when detail replaces the preview.

Decode and upload can still block. Use workers for supported geometry decode, sequence large texture transcodes, and schedule scene mutation carefully.

Track first placement-ready time separately from full fidelity.

Geometry for XR viewing distance#

XR users can lean closer than a scripted product camera. Set a minimum supported eye distance or retain enough detail for natural inspection.

Preserve:

  • silhouette from unrestricted directions;
  • holes and thin features;
  • hand-contact and placement surfaces;
  • readable labels;
  • broad specular curvature;
  • geometry that casts recognizable shadows;
  • deformation near animated joints.

Generate LODs by projected error. In AR, a one-meter object viewed from 0.3 meters can expose far more detail than the same model in a webpage.

Use lower LODs for distance and periphery with hysteresis. Review transitions during head movement; rapid, low-latency motion makes popping obvious.

Reduce draws and state changes#

XR CPU budgets are tight. One product with 30 primitives can produce 60 view submissions or more depending on renderer strategy, plus shadows.

Canonicalize compatible materials, merge small static parts where culling and interaction permit, and instance genuine repetition. Keep transparent, opaque, animated, and independently selectable regions separate as required.

Avoid one material per source component. Use atlases, palettes, vertex colors, or material parameters where they reduce measured work without wasting texture memory.

Count draws in immersive mode. Inline renderer counters may not reflect XR layer behavior.

Treat transparency as a risk#

Blended glass, particles, foliage, and layered interfaces increase overdraw and sorting complexity. Stereo views can expose sorting discrepancies. Head motion makes artifacts persistent.

Use opaque for solid regions and alpha mask for cutouts when acceptable. Limit double-sided blended surfaces. Avoid large transparent planes surrounding the user.

Test from inside, outside, and grazing angles. A bottle that looks correct from one front camera may sort incorrectly when the user walks around it.

Transmission and refraction extensions require renderer support and can be fragment-expensive. Provide a simpler material tier.

Texture and memory budgets#

Standalone headsets and phones operate under mobile memory limits. A 4096 RGBA8-equivalent image has a 64 MiB top level; full mips approach 85.3 MiB.

Resize from physical texel density and closest view. Use KTX2/Basis workflows where the renderer and target support them, and log selected GPU formats.

Normal, base color, masks, and alpha tolerate different artifacts. Test in-headset; lens distortion and display resolution change perception.

Stream high mips or close-detail variants if the architecture supports them. Release placement-only and replaced resources so quality upgrades do not accumulate every level.

Include camera textures, XR framebuffers, shadows, environment maps, and browser overhead in the device envelope.

Lighting in AR and VR#

AR backgrounds vary from dark rooms to bright sunlight. PBR material appearance depends on environment estimation and renderer features. Ensure base materials remain recognizable without perfect light estimation.

Avoid baking directional scene lighting into base color unless the asset is a fixed stylized prop. Test under neutral, bright, dim, warm, and cool environments.

Real-time shadows improve grounding but consume GPU. Use one modest placement shadow, blob shadow, or receiver strategy where supported. A large cascaded shadow system may be inappropriate for one AR product.

VR scenes need stable lighting without expensive dynamic sources. Baked or environment lighting can reduce work, but moving objects still need coherent response.

Interaction and collision proxies#

Raycasting against a million-triangle visual mesh wastes CPU and can create noisy selection. Build simple interaction proxies for selection, grab, placement, and physics.

Use:

  • bounding boxes or spheres for coarse hover;
  • convex hulls for grabs;
  • authored low-poly collision for contact;
  • semantic part proxies for selection;
  • plane-aligned placement footprints;
  • separate navigation meshes.

Keep proxy transforms and semantic IDs synchronized with visual LODs. Users should not point through a visible handle or grab empty space.

Do not embed every engine-specific collider into the GLB if the destination expects separate runtime data. Maintain a manifest.

Animation and avatars#

Skinned meshes multiply vertex work per view. Limit bone influences and morph targets against target-device pose tests. Use animation LOD: distant characters can update less frequently, use fewer bones, or switch representation.

Facial avatars can carry dozens of morph targets. Load or retain only those required. Test memory and GPU skinning in a crowd, not one avatar.

Avoid main-thread allocations each XR frame. Reuse math objects and keep reactive UI updates out of the tracking loop.

Use the session's recommended animation loop integration through the renderer. Multiple requestAnimationFrame loops can desynchronize work.

Comfort and frame pacing#

Average fps hides discomfort. Record p95, p99, missed frames, and longest frames during rapid head turns and interaction.

Avoid loading, shader compilation, garbage collection, and large uploads after immersion begins. Prewarm required materials, stage optional detail, and retain a stable low tier.

Dynamic resolution and foveation can protect frame time, but use hysteresis. Oscillating quality is visible. Geometry LOD should not thrash around one threshold.

Thermal tests matter. A standalone headset can begin at 10 milliseconds and rise above 14 after sustained use. Optimize the stable state.

Web platform delivery#

Use HTTPS and feature detection. Handle denied or unavailable XR sessions without breaking the page. Preserve an inline 3D or image fallback.

Configure GLB, KTX2, decoder, and WebAssembly MIME types; CSP worker rules; CORS; immutable cache URLs; and service worker policy.

Do not preload an XR asset on every visit if most users never enter XR. Fetch a placement LOD after clear intent while preparing decoders early enough to avoid a long blank wait.

Cancel obsolete loads when the user exits or selects another product. Dispose GPU and CPU resources under explicit ownership.

Device test matrix#

Run:

  • cold and warm acquisition;
  • enter and exit XR repeatedly;
  • placement, move, scale, and rotate;
  • closest natural inspection;
  • rapid head motion;
  • transparent and animated states;
  • low light and bright AR backgrounds;
  • network interruption;
  • session interruption and resume;
  • 15–20 minute sustained use.

Record device, browser, runtime version, framebuffer size, quality tier, artifact hash, and environmental conditions.

Test both eyes for contour and sorting. Use a screen recording plus device profiler where available.

WebXR shipping checklist#

Budget the transition into immersion as carefully as steady state. If the placement model is 800 KiB and optional detail is 6 MiB, enter with the placement tier, confirm tracking and scale, then stream the upgrade without blocking pose updates. Keep the lower tier resident until the new resources have compiled and produced one correct frame, so an interrupted transfer never leaves an empty scene.

For AR, review contrast against at least 3 real environments rather than a studio background. For VR, test both a stationary close inspection and a scene containing 8 or more instances. These cases expose different limits: transparent edge readability and scale in AR, versus duplicated materials, skinning, and stereo fill cost in VR.

Example XR budget decomposition#

Consider a standalone headset targeting 72 Hz, which leaves about 13.9 milliseconds per displayed frame. If tracking, browser, and compositor overhead consume 3.5 milliseconds, the application cannot casually claim the entire 13.9. A measured scene might spend 2.4 milliseconds on opaque geometry, 2.1 on shadows, 1.8 on transparency, 1.2 on post-processing, and 1.5 on CPU submission. That total has little margin for spikes.

Remove the cause that limits the frame. Reducing triangles will not cure 4 full-screen transparent layers. Lowering pixel ratio will help fill and post-processing more than animation CPU. Combining 30 tiny primitives may reduce submission cost while leaving the same visible shape. Repeat the capture after each change and review both eyes.

On mobile AR, include camera and environmental processing in the observed device result even when the page cannot profile every system component. A stable 60 Hz inline preview does not guarantee a stable immersive AR session. Enter AR, place the object, walk around it, approach closely, and keep the session active long enough for temperature and frequency scaling to settle.

Preserve a conservative emergency tier in memory or cache. It can disable optional shadows, replace transmission, lower resolution, and swap secondary meshes without changing physical scale or interaction anchors. Trigger it from sustained evidence rather than one slow frame. Log the tier transition with device, refresh rate, and frame percentiles so future asset releases can be compared under the same policy.

  • Modes, devices, refresh rates, and fallback are explicit.
  • Real-world units, pivot, bounds, and placement footprint are correct.
  • A placement-ready milestone exists before optional full detail.
  • Geometry survives unrestricted XR views and natural close distance.
  • Draws, triangles, materials, and shadows are measured in-session.
  • Transparency and transmission pass moving stereo review.
  • Texture formats, mips, and memory fit mobile-class devices.
  • Lighting remains legible across AR environments.
  • Interaction and collision use deliberate proxies.
  • Animation and morph costs pass realistic populations.
  • Frame percentiles and sustained thermal behavior meet the refresh target.
  • Enter, exit, error, cancellation, and fallback paths release resources.

Sources and further reading#

WebXR optimization protects a tracked, immersive deadline. Deliver a truthful, lightweight placement state, spend geometry and texture detail at natural viewing distances, minimize state and overdraw, and verify stable frame pacing on the actual phones and headsets users will hold.

Keep learning

Related guides

Platforms10 min

How to Optimize GLB Models for Three.js

Build, load, profile, cache, render, and dispose production GLB assets in Three.js with supported compression and measurable budgets.

Three.jsGLBGLTFLoader
Platforms10 min

How to Optimize 3D Models for Ecommerce Product Viewers

Design measurable 3D product assets and delivery tiers that improve ecommerce inspection without sacrificing page speed, accessibility, visual truth, or conversion analytics.

ecommerce3d product viewerweb performance
Platforms10 min

How to Optimize 3D Models in React Three Fiber

Optimize model loading, rendering, state, memory, frameloops, and responsive quality in React Three Fiber without turning React updates into frame-time work.

React Three FiberThree.jsReact