Sculpt Canvas
The missing step between 'AI generated this mesh' and 'I can actually print it'
- mesh_obj
- preview_render
- mesh_path
Image-to-3D in ComfyUI has a dirty secret the promo threads don't advertise: the meshes Hunyuan3D, TRELLIS or TripoSR hand you are triangle soup with machine-made UVs. Fine for a static prop or a print, but the instant you want to fix a lump, add a detail, or reshape something that came out wrong, you're supposed to drop it into Blender and sculpt there - losing the whole "stayed in the graph" advantage.
Sculpt Canvas answers that specific friction. It puts a real 3D sculpting viewport inside a ComfyUI node, so you can carve, inflate, smooth, and trim a mesh by hand, then hand the cleaned-up result down the graph as OBJ text, an image, or an exported .obj/.glb/.stl file. No separate app, no round-trip.
How it works
The node is two halves bolted together. The frontend (three.js, bundled and MIT-licensed - no extra install) runs a browser viewport with ten brushes: Draw, Clay, Inflate, Smooth, Flatten, Crease, Pinch, Move, Hook, and Trim. Each is bound to a number key, and the modifier behaviour is the part people love: Ctrl runs any brush in reverse (so Draw carves instead of builds), and Shift smooths without switching tools. [ and ] resize the brush, radius/strength/gloss sit under the brush grid, and there's a painted mask plus Ctrl+Z / Ctrl+Y undo.
When you hit queue, the frontend serialises the whole sculpted mesh into a JSON string (_sculpt_data) that rides inside the workflow, and the Python side parses it back into vertices, faces and UVs. From there it's pure plaintext: mesh_obj is OBJ text ready to feed into any node that eats OBJ, preview_render is a rendered square image of what's on screen, and if you set an export format it writes a numbered file to your ComfyUI output folder like Save Image does.
Nothing about this is AI, by the way - there's no model, no GPU sampling. The node is MIT and its only real Python dependencies are numpy and Pillow, which your ComfyUI already has. Sculpting here is manual work, which is exactly the point.
The inputs that matter
Forget the dense list; a beginner touches three things.
- primitive - the starting shape (sphere, cube, cylinder, torus, plane) when there's nothing sculpted yet. You can also import an OBJ/FBX/GLB/glTF and sculpt that instead; imports are auto-centred and scaled to a unit sphere, so original position and size are dropped.
- subdivision (1–5, default 4) - how dense the starting primitive is. More density means more headroom for fine detail, but the mesh caps out at 300,000 vertices, so don't crank it just because you can.
- preview_background -
viewportfor the pretty gradient backdrop, ortransparentif you want an alpha channel for compositing.
The optional row is where the exports live: preview_size (128–2048 px, default 512), export_format (none/obj/glb/stl), and filename_prefix (default sculpt, so files come out as sculpt_00001_.obj and friends). GLB is the single-file option with texture baked inside; STL is geometry-only for printing; there's deliberately no FBX writer - GLB opens in the same tools.
Installing
ComfyUI Manager: search Sculpt Canvas and hit Install. Or the manual way:
cd ComfyUI/custom_nodes
git clone https://github.com/SKBv0/ComfyUI_SculptCanvas.git
Then restart ComfyUI. No model files to download, no heavy wheels - the Python side is numpy/Pillow and the viewport runs in your browser.
Where people get burned
Three gotchas, all real, all documented by the author:
- Big meshes don't live in your workflow. Under ~12,000 vertices the mesh is embedded in the
.jsonfile. Above that it's saved toComfyUI/user/sculpt/mesheswith only a reference in the workflow - so back that folder up, and don't expect a giant sculpt to survive being emailed as a workflow alone. On reload a missing server-side copy throws a clear error telling you to re-open the workflow in the browser so the mesh re-uploads. - Imported textures are session-only. They're not stored in the workflow, so re-import the image after reopening or your textured export quietly fails. Re-import and re-queue and it works.
- Save during the upload moment. The status line shows a large mesh still uploading; save then and the workflow points at the previous copy. A failed save shows a Retry button - it won't silently fall back to the starting sphere.
Should you bother?
If you're printing props or cleaning up generated models, yes - this is the fastest way to stay in ComfyUI through the manual fix-up pass that the KB's own 3D guidance says every serious asset needs. It's no Blender replacement for real retopology, but for "reshape this lump and export a printable STL," it's genuinely the one you'd reach for.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| primitive | COMBO | sphere | 5 options: sphere, cube, cylinder, torus, plane |
| subdivision | INT | 41–5 | — |
| preview_background | COMBO | viewport | 2 options: viewport, transparent |
| _sculpt_dataopt | STRING | {} | — |
| preview_sizeopt | INT | 512128–2048 | Preview image size in pixels (max edge for viewport capture). |
| export_formatopt | COMBO | none | Also write the mesh to the ComfyUI output folder. |
| filename_prefixopt | STRING | sculpt | File name prefix for the exported mesh, like Save Image. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| mesh_obj | STRING | — |
| preview_render | IMAGE | — |
| mesh_path | STRING | — |