Draw pixel art. Paint depth. Get a real 3D model.
Try it in your browser, nothing to install.
Pixlift is a browser-based editor that turns 2D sprites into 3D models ready for Godot, Unity, Unreal, Blender, MagicaVoxel or a 3D printer. You draw on a pixel grid where every cell can be a shape (square, triangle, half block, rounded corner, circle), paint how far each pixel extrudes, and watch the 3D model build itself live next to your drawing. 100% client-side: no backend, no account, no install.
Cells are shapes, not just squares. Eighteen per-cell cross-sections (triangles, half blocks, convex and concave rounds, circles) extrude into true prisms: sloped blades, rounded gems and smooth wings instead of staircase edges, while staying 100% pixel-art to draw.
Front and back are independent. Most voxel extruders mirror the model front-to-back. In Pixlift every cell stores independent depth and color per side. Keep the symmetry lock on for the classic fast workflow, or open it and sculpt the two faces separately: a detailed front and an armored back on the same sprite.
The 3D result is always on screen. No mode switching, no "preview" button. The model rebuilds on every brushstroke.
| 2D drawing | 3D model |
|---|---|
![]() |
![]() |
![]() |
![]() |
Sword combines shaped cells (triangle blade tip, rounded pommel), variable depth (thin blade, thick guard) and front/back asymmetry: the guard gem is brighter and extrudes deeper on the front than on the back. Open docs/sword.pixlift.json in the editor.
Boat shows how one side-view drawing plus depth painting produces the whole volume: hull 8 deep, cabin 6, chimney 2, with rounded-corner cells shaping the hull. The smiley face is painted only on the front face; from behind (docs/boat-back.png) the hull is plain orange. That's the two-sided model in one picture. Open docs/boat.pixlift.json to explore.
- Modeless workspace: canvas and live 3D preview side by side
- 18 cell shapes; the mirror-X tool mirrors shapes correctly (a left triangle stamps its right-facing twin)
- Tools: pencil, line, flood fill, eraser, eyedropper (picks color + shape + depth in one click) and a dedicated depth tool that overlays the depth numbers while active
- Zoom (mouse wheel), pan (middle-drag or space + drag),
Fto re-fit - Custom canvas size (4-128 per axis, resizable at any time, drawing kept centered)
- Custom depth range (1-64 per project)
- Undo/redo (50 steps), drag painting, keyboard-first workflow
- Auto-depth: generate the depth map from color luminosity, palette index or seeded noise, with range and invert controls
- Custom palettes: add/remove colors, save/load them as files, embedded in every project
- Light and dark themes
- Autosave: unsaved work survives tab closes and crashes
| Format | What you get |
|---|---|
| GLB (glTF) | Vertex colors or a texture-atlas UV variant; imports natively into Godot, Unity, Unreal, Blender |
| OBJ | Universal geometry (no colors) |
| STL | Binary, 3D-printing ready |
| VOX | MagicaVoxel volume (shapes flatten to cubes) |
| PNG | Snapshot of the 3D view |
| SVG | True vector version of the 2D drawing; every cell is a real path |
The Optimize toggle greedy-meshes exports: coplanar same-color faces merge into maximal rectangles, typically cutting triangle counts by 5-20x. Projects save as plain-JSON .pixlift.json files (older format versions migrate automatically on open).
npm install
npm run dev # opens the editor at http://localhost:5173/Pixlift/
npm run build # production build in dist/Requires Node.js 24+. No Node that new on your machine? Test through Docker instead:
docker compose up dev # live dev server at http://localhost:5173/Pixlift/
docker compose up preview # production build at http://localhost:4173/Pixlift/Every push to main deploys to GitHub Pages via .github/workflows/deploy.yml. Forks need Pages enabled once: Settings > Pages > Source: GitHub Actions.
| Key | Action |
|---|---|
P L G E I |
Pencil, Line, Fill, Eraser, Eyedropper |
D |
Depth tool (digit overlay) |
1-8 |
Select depth |
M |
Mirror X |
F |
Re-fit the view |
Space + drag / middle-drag |
Pan |
Alt + paint |
Paint the opposite side (lock open) |
Ctrl+Z / Ctrl+Y |
Undo / redo |
Ctrl+S |
Save project |
src/
├── core/ # pure JS, no DOM; testable and reusable from a CLI
│ ├── shapes.js # shape registry: 2D outlines, culling data, mirror map
│ ├── sprite.js # data model + serialization/migration
│ ├── extrude.js # 2D sprite -> voxel Map (color + shape)
│ ├── depthgen.js # automatic depth generation
│ └── mesh.js # voxels -> BufferGeometry (prisms, culling, greedy meshing)
├── exporters/ # pure functions: data in, Blob out (GLB/OBJ/STL/VOX/SVG/PNG)
├── ui/ # canvas editor, shelf (shapes/colors/depth), popovers, theme
└── viewer/ # Three.js preview scene
The data model is the central decision. Each grid cell stores { colorF, colorB, front, back, shape }: independent depth and color per side, one shared cross-section shape (the cell is a prism column). Symmetry is just the special case front === back && colorF === colorB; nothing in the pipeline treats it specially.
The drawing plane sits at z = 0: front voxels occupy z = 0..front-1, back voxels z = -back..-1. The mesher emits one wall per outline edge with interval-based culling between neighbors; an all-square sprite produces exactly the same mesh as a classic cube mesher, and the greedy pass merges what geometry allows.
- Import a PNG and get a sprite (with auto-depth as the second step)
- Selection tools: move / copy / rotate a region
- Isometric multi-angle spritesheet export
- Fully unwrapped UV export
FBX is deliberately out of scope: it is proprietary, and GLB imports natively into every engine FBX would serve.




