Fork Notice: This is a WebGL-compatible fork of bwasty/gltf-viewer by Top-5.
Original Author: Bernhard Wasty (@bwasty)
Fork Maintainer: Top-5 (@top-5)
Original License: Unlicense (Public Domain)
This fork replaces the native OpenGL (gl crate) with webglue, a WebGL2/WebAssembly-compatible GL wrapper. This allows the same codebase to target both native desktop OpenGL and WebGL2 in browsers.
- ✅ Drop-in GL replacement: Uses
gl = { package = "webglue", path = "..." }in Cargo.toml - ✅ Zero source code changes: All GL API calls remain identical
- ✅ 56 GL functions: All core rendering functions implemented
- ✅ Full GLTF support: Loads all official sample models
- ✅ PBR rendering: Uses reference PBR shader
⚠️ Framebuffers stubbed: Screenshot functionality not yet implemented for WebGL⚠️ Native target only: Desktop OpenGL support via webglue (WebAssembly target planned)
Rust glTF 2.0 viewer, written using the gltf crate and plain OpenGL.
Current state: All official sample models can be loaded and are rendered with the reference PBR shader. Example:

Gallery with all sample models: https://bwasty.github.io/gltf-viewer/0.3.0/
Some glTF features are not yet implemented, most notably animations. See original repo #3 for details.
- Rust toolchain
- Webglue library (included as path dependency)
# Clone this repo
git clone https://github.com/top-5/gltf-viewer-webgl.git
cd gltf-viewer-webgl
# Ensure webglue is in expected path (../../webglue)
# Or update Cargo.toml path dependency
# Build
cargo build --release
# Run
cargo run --release -- path/to/model.gltfFor the original version, see bwasty/gltf-viewer:
cargo install gltf-viewerUSAGE:
gltf-viewer [OPTIONS] <FILE>
OPTIONS:
-v, --verbose Enable verbose logging (log level INFO). Can be repeated up to 3 times to increase
log level to DEBUG/TRACE)
-s, --screenshot <FILE> Create screenshot (PNG)
-w, --width <WIDTH> Width in pixels [default: 800]
-h, --height <HEIGHT> Height in pixels [default: 600]
-c, --count <COUNT> Saves N screenshots of size WxH, rotating evenly spaced around the object [default:
1]
--headless Use real headless rendering for screenshots (default is a hidden window)
[EXPERIMENTAL - see README for details]
--straight Position camera in front of model if using default camera (i.e. glTF doesn't
contain a camera or `--cam-index -1` is passed).
--scene <scene> Index of the scene to load [default: 0]
--cam-index <CAM-INDEX> Use the glTF camera with the given index (starting at 0).
Fallback if there is none: determine 'nice' camera position based on the scene's
bounding box. Can be forced by passing -1.
Note: All other camera options are ignored if this one is given. [default: 0]
--cam-pos <CAM-POS> Camera (aka eye) position override as comma-separated Vector3. Example: 1.2,3.4,5.6
--cam-target <CAM-TARGET> Camera target (aka center) override as comma-separated Vector3. Example:
1.2,3.4,5.6
--cam-fovy <CAM-FOVY> Vertical field of view ('zoom') in degrees. [default: 75]
--help Prints help information
-V, --version Prints version information
ARGS:
<FILE> glTF file name
Both .gltf and .glb files are supported. Navigate the scene with the mouse: Rotate with left click + drag, pan with right click + drag, zoom with mouse wheel.
$ curl -O https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Box/glTF-Binary/Box.glb
$ gltf-viewer Box.glb
Proper headless screenshot generation with the --headless flag currently only works on macOS.
To work around that, a Docker setup that uses xvfb is provided. Usage examples:
# Build docker image and run it with the gltf mounted in a volume.
# The image will be saved next to the gltf file.
./screenshot_docker.sh Box.glb
./screenshot_docker.sh ../models/Box.gltf -w 1920 -h 1080 --count 3 -vv
# Use pre-built docker image from Docker Hub
DOCKER_IMAGE=bwasty/gltf-viewer ./screenshot_docker.sh Box.glb
Alternatively, you can also install xvfb and use ./run_xvfb.sh directly (Linux only).