Subdivision levels (multiresolution)
- Divide (Tool > Geometry, Ctrl+D,
subdiv_divide) adds a subdivision level per SubTool and keeps the lower ones: Catmull-Clark on meshes with quads (quads stay quads), Loop on triangle meshes, flat with Smt off. - Lower Res / Higher Res (Shift+D / D,
subdiv_lower,subdiv_higher) and the SDiv slider (subdiv_level) step between levels. Detail is stored per level as a displacement in the local frame of the smoothed level below, so reshaping a low level carries it along; edits at a high level are restricted (full weighting) to the lower ones. Round trips without edits are bit-for-bit. - Mask, polypaint, paint layers, polygroups, hidden faces and UVs follow the levels (copied down, interpolated or inherited up where they changed); sculpt layers have their own detail per level; the texture is shared.
- Del Lower, Del Higher (
subdiv_delete_lower,subdiv_delete_higher) and Reconstruct Subdiv (subdiv_reconstruct: finds the lower level of a regular Catmull-Clark or Loop subdivision, keeping the mesh and its vertex order).subdiv_infolists the levels;subdiv_exportwrites the visible SubTools at another level (e.g. the base cage) in any export format. - Each level change is one undo step, as is each stroke at any level; level edits share unchanged levels copy-on-write. The two levels left last keep their topology and BVH, so stepping back and forth is instant (1-45 ms at 6.5M triangles).
- Projects save every level (project format 4). The SubTool list shows "SDiv n/m".
- Ctrl+D now runs Divide; the one-way Subdivide stays in Tool > Geometry and as
subdivide.
Gizmo 3D (moving, scaling, rotating and posing)
- Gizmo 3D modes, as in ZBrush: W Move, E Scale, R Rotate, Q back to Draw (top shelf, Transform palette, F3). Move has axis arrows, plane squares and a view-plane centre; Rotate has axis rings and a view ring; Scale has axis boxes and a uniform centre. Shift snaps (15 degrees, a round grid step, 10%). The amount shows beside the gizmo while dragging. Dragging off the handles still navigates; Ctrl still masks.
- Transforms move the active SubTool, or only its unmasked part: partly masked vertices move partly, hidden ones never. Falloff eases the movement in over a distance from the mask's edge (measured along the surface, as a share of the size) for soft joints when posing. With symmetry on, a masked transform is mirrored across the symmetry plane.
- Pivot: follows the centre of what moves; Alt+drag the gizmo to move it (or turn its axes) without the model,
Alt+click the model or To Surface to put it on the surface, Reset; World or Surface axes (Y along the normal,
turning with rotations). The gizmo follows undo / redo of its own steps and is saved in projects (
gizmokey, no format bump). - Gizmo 3D panel: pivot, options and numeric Move / Rotate / Scale with Apply; All SubTools (Transpose All, one undo step per SubTool).
transformcommand (translate, rotate, scale, pivot, orient, masked, falloff, symmetry, all); each gizmo drag is echoed to the console as the command that repeats it.- One undo step per drag that restores positions bit for bit. Sculpt layers move with the surface (the base and every layer's offsets). Topology, quads, UVs, textures, polypaint and polygroups are untouched.
- Fast on big meshes: a drag recomputes from the drag's start (no drift), transforms only the moving vertices through a per-weight lookup table on several threads, turns normals of rigid parts and recomputes only where the movement varies, uploads only the changed vertex range and refits the BVH once on release. On 1.3M triangles: about 2 ms to transform and 7 ms to upload per drag frame, 20-40 ms on release.
Normal, displacement and AO map baking
- Tool > Bake (and the
bakecommand) bakes a high-poly source (one SubTool, or every visible one but the active) onto the active SubTool's UVs: tangent-space normal, object-space normal, displacement, ambient occlusion, cavity and colour (polypaint or painted texture) maps, 1K to 8K. - Tangent-space maps use MikkTSpace tangents (vendored, zlib), as Blender, Unreal, Unity and Godot compute them; OpenGL or DirectX green convention. Unit-tested to decode to the high-poly's normals within 0.2 degrees on average.
- Rays along the low-poly's smoothed normals through a front / rear cage, measured automatically by default or set by hand, keeping the high-poly hit nearest the low-poly; 1-16 rays per texel of anti-aliasing; padding around UV islands; tile-parallel on every core over a dedicated thread-safe BVH, in the background with progress and Cancel.
- Displacement as a 16-bit PNG (mid-grey = 0, scale reported) and a 32-bit float OpenEXR in world units.
- The baked normal map shows on the low-poly in the viewport (new normal-map shader with per-corner MikkTSpace tangents), with a Preview Normal Map toggle.
- Send to Unreal imports the baked normal map too (
T_<Name>_N, normal-map compression, green flipped for OpenGL maps) when the editor runs on the same computer. - Maps are written as
<SubTool>_normal.png,_ao.png,_displacement.png/.exrand so on, beside the last export by default.
Quad retopology and detail projection
- QRemesh (Tool > Geometry > QRemesh,
qremesh): automatic quad retopology like ZBrush's ZRemesher. A field-aligned method after Instant Meshes (Jakob et al. 2015; field formulas follow its BSD-3 reference code, credited in THIRD_PARTY_NOTICES.md): a multi-resolution 4-RoSy orientation field and position field, polygon extraction, then every polygon split into quads and relaxed onto the sculpt. The result is 100% quads, 2-manifold and closed where the sculpt is, within about 5% of the target count. - Options: Target Polygons with Half / Same / Double, Adaptive Size (curvature-driven quad size), Keep Groups (edge loops along polygroup borders, groups kept), Detect Edges (loops on hard edges over 50 degrees), Use Polypaint (red = up to 4x the density, blue = down to a quarter), Symmetry (one half remeshed and mirrored, welded on the seam), Keep Original (the old SubTool kept hidden below, for ProjectAll).
- Runs in the background in the app with a progress bar and Cancel; one undo step. Mask and polypaint are interpolated onto the new mesh; sculpt layers are baked.
- ProjectAll (Tool > SubTool > Project,
project_all): moves the active SubTool onto the other visible SubTools (rays both ways along the normal, nearest hit within Dist, else the closest point) and takes their polypaint. Dist, Mean, PA Blur, Geometry / Polypaint toggles, an optional singlesource; respects the mask and hidden faces; shape goes into the active sculpt layer, colour into the active paint layer; one undo step. - Fast on dense meshes (all threads, a read-only BVH): 1.3M triangles to 5,000 quads in 1.7 s, to 100,000 in 6 s; ProjectAll onto 1.25M vertices in 0.6 s (10-core desktop).
- New guide chapter "Quad retopology and detail projection", glossary entries; UI test
tests/ui/retopo.sfui, unit teststests/test_retopo.cpp(manifold, quad %, target count, Hausdorff distance, projection error).
Performance at tens of millions of polygons
- Benchmark:
sculptforge --bench(with GPU upload and orbit timings) andsculptforge-cli --benchbuild a sphere divided to 4M / 16M / 32M triangles and measure every brush per dab (kernel, normals, BVH refit, upload), undo, level stepping, project save / open and orbit. Numbers before and after in docs/performance.md. - A persistent thread pool (core/ThreadPool) runs every brush kernel (all brush types, recipes, mask and paint),
normal updates, BVH queries, refits and builds, and project CRCs. Work is split into fixed blocks with partial
sums added in order, so results are identical to one thread (
set_multithreading). - Partial GPU updates: meshes track dirty vertices (a bit each, plus 2048-vertex blocks), and the renderer keeps vertices in first-use order of the triangle list (core/UploadOrder), so a dab uploads a few short ranges of what it changed instead of most of a subdivided mesh. A medium dab at 33M triangles: 398 ms -> 10 ms.
- Memory: the per-triangle face normal cache and its stamps are gone (normals are summed per vertex, same result), the adjacency list has no spare capacity, the renderer keeps no CPU copy of the curvature: 90 -> 62 bytes per triangle for a sculpting mesh.
- The first polypaint stroke on an unpainted mesh keeps the (empty) paint stack for undo instead of a copy of the whole mesh.
- Projects: archives stream to disk (no in-memory copy), entries are read in place, CRCs are computed in parallel, arrays are copied rather than converted byte by byte; ZIP64 past 4 GB (smaller archives are byte-identical to before).
- The window has no multisampling; the 3D view antialiases in its own target (Renderer::drawView), so it can use fewer samples when the GPU has no room, and Fast Navigation draws scenes of 10M+ triangles without antialiasing while the view moves. A SubTool that runs the GPU out of memory is not drawn (status message).
- Preferences > Performance: Antialiasing (Off / 2x / 4x / 8x), Fast Navigation, Multithreading, the last
stroke's cost per dab and memory;
perf_infoandset_multithreadingcommands.
Polish of the v0.5 features (known issues fixed)
- Auto UV on a SubTool with a painted texture now moves the paint and every texture layer onto the new UVs
instead of scrambling it (each texel of a new UV triangle samples the old texture at the same point of the same
triangle, islands padded 8 texels); one undo step restores the old UVs and texture (
uv_auto keep_texture=falsefor the old behaviour). 1.05M triangles, 4K texture with a layer: 0.2-0.3 s. - Keep Texture (Tool > Remesh, Tool > Geometry > QRemesh;
keep_textureonremeshandqremesh, default on): the rebuilt surface gets Auto UVs and the texture, all layers, is projected onto it from the old surface, in the same undo step. Voxel Remesh of a painted SubTool runs in the background with progress and Cancel. Merging SubTools (subtool_merge_down,subtool_merge_visible) keeps their textures in one texture on new Auto UVs. - Decimate no longer scrambles a texture at UV seams (seam vertices stay in place).
- Auto UV no longer crashes or folds UVs on dense smooth meshes (e.g. the default 82k-triangle sphere): fixed in third_party/xatlas. UV islands are capped at about 4000 triangles, so a 1.3M-triangle sculpt unwraps in about 16 s instead of minutes.
- Subdivision levels: Voxel Remesh, Decimate, QRemesh, Subdivide, Delete Hidden and merging or splitting SubTools say in the status line that they removed the levels and which one became the new base ("Subdivision levels removed: SDiv 3 of 5 kept as the new base"); undo restores every level (now covered by tests).
- Subdivision levels: a sculpt layer's fine detail now turns and bends with a low level rotated with the Gizmo 3D or reshaped (layer details are stored relative to the surface). Project format 5; format 4 projects are converted when they open.
- Subdivision levels: only the active SubTool keeps its recently visited levels cached; selecting another SubTool frees 50-170 MB per SubTool with 1.8M triangles (the first level step after coming back takes about 0.1 s).
- QRemesh: Symmetry mirrors across the model's own middle plane, so models away from the world centre work. A
model that isn't mirror-symmetric is remeshed without symmetry and the status line says so; a nearly symmetric
one keeps mirrored topology on each side's own surface. Symmetry is on by default in the panel; new
symmetry_centerargument for a fixed plane. - QRemesh: small separate pieces (eyes, rivets) are no longer dropped: they are remeshed on their own with at least 32 quads, or kept as they were. Parts thinner than a quad (blades, fins, slabs) keep both sides and their hard edges (thin slab: mean error 2.2% -> 0.05% of its size, Hausdorff 8.8% -> 2.6%).
- Top shelf: the Vertex / Texture paint target is hidden while the SubTool has no texture, instead of sitting there greyed out (docs/ui-design.md now states the rule for contextual shelf buttons); Draw Size and Strength shrink to fit when the row is full.
- Exports: the
.mtland PNGs written beside a model whose file name has spaces use_instead (OBJ'smtlliband MTL'smap_Kdsplit names at spaces). Textured exports were validated with other tools: Khronos glTF validator (no errors or warnings), OpenUSD's validators (no issues), ufbx strict mode, and a texture orientation check per format;tools/export_check/run.shrepeats it. - UI tests:
wait_idlewaits for several idle frames in a row, which fixes the flakyui_lightboxunder a loaded parallel ctest.
Changed
- Wireframe (PolyF) is Shift+F only: W is now the Gizmo 3D's Move, as in ZBrush.
Downloads
New here? install/ explains
which file to pick, or install with one command:
curl -fsSL https://raw.githubusercontent.com/islandmed/SculptForge/main/install/install.sh | sh (macOS / Linux),
irm https://raw.githubusercontent.com/islandmed/SculptForge/main/install/install.ps1 | iex (Windows PowerShell).
Each file is also attached without its version number (e.g. SculptForge-macos.dmg) so links to
releases/latest/download/... always get the newest build.
| Platform | File |
|---|---|
| Windows 10/11 (x64) | SculptForge-…-windows-x86_64.exe (installer) or .zip (portable) |
| macOS 11+ (Apple Silicon and Intel) | SculptForge-…-darwin-universal.dmg |
| Ubuntu / Debian / Mint / Pop!_OS | sculptforge_…_amd64.deb or …_arm64.deb |
| Fedora / RHEL / Rocky / Alma 8+ | sculptforge-…x86_64.rpm or …aarch64.rpm |
| Studio pipelines (VFX Reference Platform) | SculptForge-…-linux-…-vfx2026.tar.gz (GCC 14.2, glibc 2.28) or …-vfx2027.tar.gz (glibc 2.34), with the Python 3.13 module |
| Any Linux | SculptForge-…-linux-x86_64.AppImage or …-arm64.AppImage |
| Arch Linux | yay -S sculptforge (AUR) |
The builds are not code-signed yet. macOS: right-click the app → Open the first time.
Windows: if SmartScreen appears, choose More info → Run anyway. Checksums are in SHA256SUMS.txt.