How to Embed 3D Models on the Web
At 4/19/2024
When Shopify announced they added 3D scanning to their iOS 17 app, I immediately wondered, “How does that work?”
To be clear, I wasn’t wondering how the scanning worked. I thought I knew that (I was wrong). I wanted to know the basics. How do you embed 3D models in web pages? How do you do so without slowing down your site? I didn’t even know what file formats 3D models use.
So consider this a bit of 3D models on the web 101. We’ll review the file formats, 3D model viewers, user experience, optimizations, and proposed future web standards.
3D Model File Formats
There are four 3D model file formats that you should know and two that you will actually use for embedding:
- .gltf: Graphics Library Transmission Format (glTF) is a ISO/IEC standard for describing 3D models. It stores data in JSON with references to other files for textures, etc.
- .glb: This is the binary version of the glTF. It combines the model itself, textures, and materials into one compact file, perfect for web embedding.
- .usd: Originally developed by Pixar, the Universal Scene Description (USD) is Apple’s darling format. There are multiple file formats within USD including .usd, .usda — ASCII encoded, .usdc — binary encoded, and the most popular, .usdz.
- .usdz: A zip archive version of USD. Both .usd and .usdz have limited support outside of Apple products, but there is a new effort to standardize USD as an open standard.
Remember, these are just the web-friendly formats. Others like OBJ and STL exist for different purposes like 3D printing or model sharing.
For the most part, you only need to concern yourself with .glb and .usdz. And because .glb can be used by more browsers, it is the typically the baseline.
Bring Your Own Model Viewer (BYOMV)
Unlike images and videos, browsers don’t have a built-in way to showcase 3D magic. That’s where model viewers come in. They’re like specialized translators, taking your 3D model and turning it into something your browser can understand.
One such viewer is <model-viewer>, an open-source web component maintained by Google, compatible with gltf/glb formats. While other options exist, like three.js which is often used for more immersive experiences, <model-viewer>
seems to be the most popular option for web embedding. Shopify, which seems to be doing a lot of things right when it comes to 3D models, is using <model-viewer>
under the hood.
Augmented Reality (AR) Modes
In addition to viewing a 3D model in a web page, some devices support augmented reality modes which use the device’s camera to place 3D models in a real-world context.
The <model-viewer>
supports various AR modes. You can add and style a button visible only on devices that support AR mode that prompts the user to view the model in their space.
<model-viewer>
automatically uses WebXR or SceneViewer on Android. By default, it uses WebXR on Android which is faster and stays in the browser. On iOS and on the Vision Pro, the AR mode is provided by QuickLook. QuickLook requires a .usdz file so <model-viewer>
generates one on the fly.
3D Model Viewing UX
Shopify sets a great example for 3D model UX:
- Start with a poster image and an overlay hinting at interactive content.
- Load the 3D model upon user interaction, displaying a progress bar.
- Once loaded, animate the model to demonstrate interaction possibilities.
- For AR-capable devices, offer an additional button for AR mode.
Much of this functionality is built into <model-viewer>
if you take the time to configure the component properly and add animations and icons.
3D Model Performance
3D models are large files, so it’s crucial to delay their download until the user starts to interact with them. <model-viewer>
provides a lazy-loading feature that should solve this problem. Unfortunately, it has a bug where if you use lazy-loading, the progress bar won’t work properly.
But even if <model-viewer>
didn’t have this bug, it still wouldn’t be optimal because <model-viewer>
is 245K of JavaScript on its own. It would be better to only download this JavaScript if we knew someone was going to interact with the 3D model.
That’s why my colleague Scott created the Lite Model-Viewer web component. He was inspired by Paul Irish’s Lite YouTube Embed web component which delays YouTube’s large JavaScript footprint until the user clicks on the poster image. Lite Model-Viewer works the same way, and at only 1.4K compressed, it is substantially smaller than loading the full <model-viewer>
.
Compressing 3D Models
Is it possible to compress 3D models similar to the way we use compression on images and video? Yes, but our options are limited.
Outside of zipping up 3D models, the primary compression option is Draco. Draco is an open source library from Google that compresses 3D models and their textures.
To see how much impact Draco might have, I downloaded four original .usdz files from Shopify. I used Blender to convert the files into .gltz (the zip version of .gltf) and .glb files. I then uploaded the .gltf files into Cloudinary and used its Draco integration to test the compression.
💡When you import a .usdz file into Blender, it will likely be placed under the default 3D cube in a new document. You will need to delete that cube, but your delete key may not work. Change Blender’s key mapping to “Industry Compatible” to fix it. Thanks to Jonathan Wight for the tip.
The following table lists the respective 3D model file sizes at each step of the process:
Model | .usdz | .gltz | .glb | draco .gltz | draco .glb |
---|---|---|---|---|---|
Coffee Mug | 7.3 MB | 6.6 MB | 6.7 MB | 1.3 MB | 416 K |
iPad Holder | 9 MB | 8.1 MB | 8.2 MB | 1.8 MB | 591 K |
Piggy Bank | 10.3 MB | 9.2 MB | 9.3 MB | 2.1 MB | 854 K |
Table Lamp | 8.9 MB | 7.8 MB | 7.9 MB | 1.8 MB | 786 K |
There are significant file savings if you use Draco. I assume there is some drop in quality, but I have trouble telling the difference.
Web Standards and the End of BYOMV?
In 2021, Apple proposed a new html element, <model>
, that would work similar to the <video>
element and make it much easier to embed 3D models into web pages. This proposal moved to the Immersive Web Community Group where work on a draft specification has continued.
The proposed syntax for the <model>
element may look something like this:
<model style="width: 400px; height: 300px" interactive>
<source src="/wp-content/uploads/2024/01/ipad-holder.usdz" type="model/vnd.usdz+zip">
<source src="/wp-content/uploads/2024/01/ipad-holder_draco.glb" type="model/gltf-binary">
</model>
Code language: HTML, XML (xml)
The specification is still a long way from being standardized, but it is possible to experiment with <model>
by turning on the “HTML <model>
element” feature flag in Safari.
You shouldn’t use <model>
on any production sites. In fact, <model>
is so young that the draft specification contains more spots for discussion than it does details on how the new element might work. And there are many use cases where WebXR might be a better solution.
Despite this fact, I’m excited by the possibility of <model>
ending the era of bringing your own model viewer. That’s no shade on <model-viewer>
. It is an amazing open source project that makes embedding 3D models possible.
But if 3D models are going to spread more widely—either as a way to provide reassurance to ecommerce shoppers that what they’re buying will look as they expect or as a piece of new immersive experiences like Apple’s Vision Pro headset—then adding 3D models to a page should be as simple as adding images and video.