GLB Viewer & Compressor — Open, Inspect and Shrink .glb / .gltf Online
Make your own glb viewer
Drop a .glb or .gltf file and view it instantly in your browser — no upload, no software. Inspect the mesh, check the materials, then compress and optimize the file for your game. Free, no signup.
A GLB viewer in the browser decodes the file inside the tab and draws it with WebGL. Drop a .glb or .gltf on the page and the model is on screen in a few hundred milliseconds on a desktop; there is no upload step, no installer and no account. A GLB is a glTF 2.0 asset packed into one binary file: a 12-byte header, a JSON chunk that describes the scene graph, and a BIN chunk that holds vertex buffers, index buffers and, usually, the embedded images.
The same page is the inspection and shrinking step of a game pipeline. You open the export, look at the wireframe, the normals, the UV islands and the material slots, confirm nothing broke on the way out of Blender or Maya, then compress the file and download a copy for your engine. This page covers what each inspection view catches, the three compression levers and the order to pull them in, and the budgets a browser scene actually has to live inside.
Open a .glb Right Here
Drag a file onto the drop zone, or pick one with the file dialog. The page reads it through the File API as a Blob URL plus an ArrayBuffer and parses it in the same tab. Open your browser network panel while you do it: no request carries the model. Nothing is queued, nothing is written to a server, and closing the tab discards it.
Local matters twice. Privacy first: unreleased characters, client work under NDA, scanned assets you paid for. Sending those through a third-party converter is a licensing problem before it is a performance problem. Latency second: a 40 MB GLB over a 10 Mbps upstream connection is roughly half a minute of waiting before any conversion even starts, and that wait changes how often you actually check a file. A local read off an SSD is a fraction of a second, and the parse cost is CPU work on your own machine.
Accepted input: .glb is the single-file case. .gltf is the same scene as JSON, so it usually arrives with a .bin buffer and a folder of images. Multi-select them, drag the whole folder, or drop a zip and the viewer resolves the relative URIs. Embedded data URIs work without sidecars. Textures can be PNG, JPEG, WebP or KTX2 (Basis Universal), and geometry can be Draco- or meshopt-compressed, because the viewer ships both decoders and reads the extension list in the JSON chunk to decide which one to use.
What it renders: PBR materials under one directional light plus an optional environment map, a toggleable 1 m grid so you can read real scale, a clip list for every animation in the file, and a stats panel with triangle count, vertex count, node count, an estimate of draw calls, and the pixel dimensions and byte size of every embedded image. Memory is the only hard limit. A 100 MB GLB usually opens on a desktop; a phone tab can be killed by the browser before it finishes parsing.
What a Browser GLB Viewer Does Differently
The alternative is a round trip: open the DCC, import, look, export, load the engine, notice the problem, go back. Each hop costs minutes and each hop can introduce its own change, so you end up debugging the pipeline instead of the asset. Keeping the inspection in the same tab where the file already lives removes the round trip and, more usefully, means the numbers you read are the numbers in the file you are about to ship.
Inspect: Wireframe, Normals, UV Layout, Materials
Four views catch most bad exports before they reach the engine. Wireframe shows triangle density and reveals where the exporter triangulated an n-gon. Normals shows face orientation, so an inside-out surface reads as black under a single directional light. UV layout flattens the UV channel to a grid with the texture behind it, which makes overlapping islands, stretched texels and geometry outside the 0 to 1 range obvious. Materials lists every material with its textures, alpha mode, double-sided flag and color space settings.
Inspect before you compress, always. Draco and meshopt rewrite vertex buffers and change the vertex layout, and a texture resize can hide a seam that was already there. If you compress first, you stop being able to tell whether an artifact is yours or the compressor's.
The stats panel is part of the inspection. Write down triangle count, vertex count, node count, material count and the dimensions of each embedded image before you touch anything. Those are the baseline numbers you compare against after every compression step, and they tell you which lever is actually worth pulling.
| Symptom | What the view shows |
|---|---|
| Faceted shading on a surface that should be smooth | Wireframe plus normals: vertices split along every edge, or a hard edge where smoothing groups were dropped |
| Dark or inside-out surfaces | Normals: faces pointing inward light up black against a single directional source |
| Texture stretches, bleeds or tiles wrong | UV layout: overlapping islands, islands pushed outside 0 to 1, or texel density that varies across the mesh |
| Model looks right but is heavier than expected | Wireframe: triangle density in flat areas, plus the triangle count in the stats panel |
| Base color looks washed out or too bright | Materials: the sRGB flag on the baseColor texture. Linear on a color map looks wrong immediately |
| Black or missing texture after engine import | Materials: image referenced by URI but not packed into the BIN chunk, so the sidecar file went missing |
| Transparent parts sort behind solid ones | Materials: alphaMode BLEND where MASK would do, and double-sided flags doubling the overdraw |
| Lightmap missing on the second UV channel | UV layout on TEXCOORD_1: absent, or present but empty because the exporter dropped it |
Compress a GLB Without Breaking It
Three levers, and they are not equal. Dropping data that nothing references is free and reversible by re-exporting. Re-encoding textures removes most of the bytes in a typical asset, because images dominate the file. Geometry compression is the one that can break a model, so it goes last.
None of these has a guaranteed ratio. A GLB that is one 4096 by 4096 PNG behaves nothing like a GLB that is mostly vertex data, and a mesh-heavy scene with 30 textures at 512 will not respond the same way as a single character with one 4K atlas. Measure after every step rather than trusting a number from someone else's asset.
Decoders are a shipping constraint, not a detail. Draco needs a Draco decoder module, meshopt needs MeshoptDecoder, and KTX2 needs a transcoder with the right target formats. three.js ships GLTFLoader but you have to wire up DRACOLoader, MeshoptDecoder and KTX2Loader yourself; Babylon.js and Unity glTFast have equivalents. If you compress with an extension your runtime does not know, the model loads black or throws, and it will look like a file corruption rather than a configuration mistake.
- Lever 1 — Drop unused dataImages that no material references, duplicate materials that differ only by name, morph targets with all-zero deltas, TEXCOORD_1 when there is no lightmap, cameras and lights that came along from the Blender exporter, animation clips on static props, and KHR_ extensions your runtime ignores. This step is lossless, and it is also the step people skip.
- Lever 2 — Resize and re-encode texturesThis is where most of the byte reduction usually comes from. Base color and emissive maps tolerate JPEG or WebP at a lower quality because they are already sRGB and carry no fine gradients. Normal, metallicRoughness and occlusion maps should not go to JPEG, because compression ringing shows up as shading artifacts across the whole surface; keep them PNG or move them to KTX2 with UASTC. KTX2 through KHR_texture_basisu stays compressed in GPU memory, which cuts VRAM as well as file size, and ETC1S is the cheaper option for color maps.
- Lever 3 — Compress the geometryTwo options in practice. EXT_meshopt_compression decodes quickly and is a good default for assets that stream in during play. Draco usually produces smaller static meshes but costs more decode time and moves work onto the main thread unless you use a worker. Pair either with KHR_mesh_quantization: 14 to 16 bit positions, 10 or 8 bit octahedral normals, 12 bit UVs. Quantization shifts geometry slightly, so check the smallest details and any mesh used for collision.
01
Open the file and record the baseline: triangles, vertices, nodes, draw call estimate, image list with dimensions, total byte size.
02
Strip unreferenced data first. Reload and compare the stats. Nothing should change visually, and the file should get smaller.
03
Handle textures next, largest first, and re-check at the same zoom level the texture will be seen at in play.
04
Compress geometry last with meshopt or Draco plus quantization, then reload and re-inspect the wireframe, the normals and the UV layout.
05
Export GLB, then load that exact file in the engine with the matching decoders enabled before you delete the original.
GLB vs glTF vs FBX — Which One Your Engine Wants
glTF 2.0 is the runtime format. GLB and .gltf are two containers for the same data: GLB puts the JSON and the binary buffer in one file, .gltf keeps them separate as readable text plus sidecars. FBX is a DCC interchange format that predates glTF and is still what most riggers and animators hand off, and OBJ is geometry only, with no animation and no PBR materials at all.
Axis and unit conventions cause more import bugs than file size does. glTF is meters, Y-up, right-handed, with cameras looking down -Z. FBX exporters disagree about units, and a centimeters versus meters mismatch shows up as a model roughly 100 times too small or too large. Blender's glTF exporter converts Z-up to Y-up for you; disable that and the model arrives lying on its side. Check the bounding box in the viewer against a known dimension before you blame the engine.
| Format | What it is | Where it is the natural choice |
|---|---|---|
| GLB | glTF 2.0 as one binary file: JSON chunk plus BIN chunk with buffers and images embedded | Runtime in the browser, Godot, Unity with glTFast, Babylon.js, three.js. Also the right format to send to another person |
| .gltf plus .bin and image files | The same scene as plain JSON with external buffers and textures | Version control and hand editing. The JSON diffs cleanly, which GLB does not |
| FBX | Autodesk interchange format with its own SDK and inconsistent unit handling | Getting rigs, animation and blend shapes out of Maya or 3ds Max. Not a runtime format |
| OBJ plus MTL | Geometry and a basic material file, no animation, no PBR | Static props and 3D printing. Nothing to gain for a game asset |
| USDZ | Apple's uncompressed AR container | iOS Quick Look and AR viewing, not game rendering |
| STL | Triangle soup with no UVs, materials or normals data beyond face normals | 3D printing and mesh repair only |
Optimize for the Web: Draw Calls, Texture Size, Poly Budget
Treat these as starting points you tune per project, not limits. A browser scene that holds a steady frame rate on a mid-range laptop is usually under a few hundred thousand triangles and, far more importantly, under a few hundred draw calls. Instancing and material merging move the first number; nothing moves the second except combining geometry.
Draw calls are counted per mesh per material. Two hundred props that each carry their own material cost two hundred draws even if each is only a few hundred triangles, and the CPU cost of submitting them can exceed the GPU cost of the geometry. Merge static geometry that shares a material, atlas small textures into one image, and instance repeated props. Transparent materials cost more than their triangle count suggests because they sort and blend per pixel, and shadow casting re-renders the same geometry into a depth map.
Texture size usually dominates both the file and the VRAM, which is the part people get backwards. A 4096 by 4096 RGBA8 texture is 67,108,864 bytes in memory before mipmaps, and mipmaps add roughly a third on top; a 100k-triangle mesh with 4-byte positions, normals and UVs is a few megabytes by comparison. One careless 4K normal map outweighs the entire mesh it sits on. KTX2 keeps the texture compressed in GPU memory, which is a different saving from file size and often the one that matters on mobile.
Color space belongs in this list because it is routinely wrong. Base color and emissive are sRGB. Normal, metallicRoughness and occlusion are linear. Swap them and the material looks either washed out or too dark, and no amount of lighting tweaking fixes it because the data was interpreted wrong at load time.
| Target | Triangles | Draw calls | Texture budget | Download size |
|---|---|---|---|---|
| Mobile browser scene | 50k to 150k total | under 100 | 1024 max, 512 average | 2 to 5 MB |
| Desktop browser scene | 200k to 500k total | 150 to 300 | 2048 max | 5 to 15 MB |
| Single hero asset | up to about 1M | 1 to 5 | 2048, KTX2 | 10 to 20 MB |
| Background props | under 5k each | shared atlas and instancing | 256 to 512 each | shared with the atlas |
Inspect a Real Model Before You Compress
Reading about topology is not the same as rotating it. The Blender Model Gallery is embedded on this page in wireframe mode, so you can spin a real export and look at the triangles the engine will actually draw rather than the clean quads the modeller saw.
Watch three things while it turns. Curvature: where triangles bunch up is where the exporter added them, and a flat 20-triangle wall next to a 20,000-triangle sphere is normal. Seams: a shading change across an edge means the vertices were split there, which is correct at a UV seam and wrong on a smooth surface. Silhouette: the outline is what a player reads at distance, and it survives a decimation pass far better than interior detail does.
The same budgets apply to the assets shipped in Mini World and The Cyclops' Island, both of which run in a browser tab through the 3D game builder. A prop that is 40k triangles on its own is fine; forty of them in one scene is not, and the wireframe view is where you find that out before the frame rate does.
Walk into the world it belongs to
A sprite is a character with nowhere to stand. The last step is the one nobody else offers: take the sheet you just built and put it in a world someone can walk around in — a small island, a planet, a rainy street corner. Every world on this site was made from one written description and published as a page you can play.
FAQ
Do I have to upload my .glb to view it? +
No. The file is read through the browser's File API and parsed in the tab; opening, inspection and compression all run locally. Open the network panel if you want to confirm that no request carries your model. The page itself has to be loaded once, so you need a connection to reach the tool, but the model never leaves the machine.
Does the tool modify my file? +
No. The file on disk is never touched. Every operation runs on an in-memory copy and compression produces a new download, so you keep both versions. Hold on to the original until you have loaded the compressed file in your engine.
Is the compression lossy? +
It depends which lever you pull. Dropping unreferenced data is lossless and reversible by re-exporting. Resizing and re-encoding a texture is lossy, and quantizing vertex positions and normals is lossy; both are usually invisible at sensible settings and obvious at aggressive ones. Re-check the normals, the UV layout and the smallest details of the mesh after each step.
Which formats can I open and export? +
Open: .glb, .gltf with its .bin and image sidecars, and zipped versions of either. Textures can be PNG, JPEG, WebP or KTX2, and Draco- or meshopt-compressed geometry is decoded on load. Export: GLB, or .gltf plus a separate .bin when you want the JSON readable in a diff, optionally with KTX2 textures.
Is it free? Do I need an account? +
Free, and there is no signup, no account and no watermark on the output. The work happens on your machine, so there is no per-file server cost to pass on to you.
Will my engine import the compressed file? +
Usually yes, as long as the runtime is configured for the extensions you used. Draco needs a decoder, meshopt needs MeshoptDecoder, and KTX2 needs a transcoder; three.js, Babylon.js and Unity's glTFast support all three but not by default. Godot imports a plain .glb with no setup. Load the compressed file in the engine once before you delete the original.
Back to the 3D Game Builder
All 31 finished 3D worlds, games and scenes live on one page — every one of them playable.