Poly-Gone Spheres


A procedural planet editor for building a base shape with nodes, sculpting it non-destructively, and rendering it through a sparse GPU SDF.

Poly-Gone Spheres project preview
2026

Poly-Gone Spheres

Poly-Gone Spheres is a procedural planet editor I designed and built alongside the Aurora engine during my 20-week graduation project. A node graph creates the planet's starting shape, after which you can sculpt it non-destructively and see the result update in the viewport. The same procedural definition and edit history can then be saved as a volume or extracted as a conventional mesh.

The name began as a joke about removing polygons through subtractive sculpting. Halfway through the project I replaced the mesh-based viewport with raymarching, so the editor had quite literally become “poly-gone.” That pivot also shaped the rest of the architecture: instead of repeatedly rebuilding a large mesh, the editor now updates only the sparse SDF bricks touched by a procedural or sculpting change.

Poly-Gone Spheres editor with a procedural node graph and generated planet
The node graph defines the repeatable base shape; sculpting adds an ordered, non-destructive layer on top.

How the renderer evolved

The final renderer was not the starting point. I changed representation several times as editing cost, memory use, and planet scale exposed different bottlenecks. Each version left something useful behind, even when its central approach was replaced.

  1. One dense volume, one mesh

    The first version stored the entire signed-distance field in one dense 3D texture and regenerated one mesh from it. It was straightforward, and allowed me to quickly test the prototype, but even a small edit could trigger a large amount of meshing work and a lot of undesired slow-down.

  2. Chunked mesh generation

    I divided the same dense texture into chunks and generated a mesh per chunk. Vertex and index data lived in sub-slices of large static buffers, compute work compacted the visible chunks, and one indirect draw submitted them. Local edits became cheaper, but meshing was still substantial and the dense texture imposed a fixed memory ceiling: the planet could use neither significantly less memory nor grow beyond the allocation.

  3. Raymarch the dense field

    I then tried rendering the distance field directly. Raymarching was slower while the scene was idle, but edits became nearly free because there was no mesh to rebuild, just a 3d texture update. For an editor where changes are frequent and can cover large regions, that was the more useful tradeoff.

  4. Make the SDF sparse

    Sparse storage solved the remaining memory problem. Surface bricks are allocated from bindless 3D texture blocks only when needed, so an empty region costs metadata rather than a full-resolution volume. This made larger planets practical without reserving one enormous texture up front.

  5. From chunk proxies to one planet proxy

    My first sparse renderer drew an instanced cube for every resident chunk in one call. It worked, and was certainly faster than the previous raymarcher, but isolated cubes created overdraw and rear-side chunks were still rasterized. A single planet-scale proxy proved simpler: each ray stops at the first surface, so the rear half never needs to produce a separate proxy draw.

  6. Skip empty space hierarchically

    Finally, hierarchical DDA traversal added coarse chunk and macrocell skipping before walking individual bricks. SDF sampling now begins only after the ray reaches populated storage, which is important when most of a planet's bounding volume is empty.

Current architecture

The editor separates build-time node generation, CPU-side authoring and bookkeeping, and GPU-side volume generation and rendering. That separation lets the expensive parts move to background work without making the editable graph or sculpt history depend on renderer resource lifetimes.

  1. 1Build time

    Generate the node system

    KDL metadata generates typed node shells, editor controls, serialization, and registry entries.

  2. 2Authoring · CPU

    Compile the planet graph

    The visual editor writes YAML. The runtime validates its links and types, removes unused work, and produces an executable SDF program.

  3. 3Sculpting · CPU

    Plan sparse updates

    An ordered sculpt journal and BVH identify affected bricks while background work updates residency and builds the next frame plan.

  4. 4Generation · GPU

    Regenerate dirty bricks

    Render-graph passes upload compact jobs and evaluate only the procedural program and edits needed by each dirty brick.

  5. 5Viewport · GPU

    Skip to the surface

    A planet-scale proxy starts the ray, then hierarchical DDA traversal skips empty chunks and bricks before SDF sampling begins.

  6. 6Output · CPU

    Preserve or extract the result

    Volume export preserves the pipeline and journal; background extraction samples the same result into an indexed GLB mesh.

Aurora and Poly-Gone Spheres

Aurora provides the engine boundary

Aurora supplies the application lifecycle, render graph, rendering hardware interface, bindless resources, synchronization, transfers, shader compilation, and shared threading facilities. Poly-Gone Spheres uses those systems instead of owning another renderer beneath its editor.

Poly-Gone Spheres owns the planet workflow

PGS owns the visual node language, pipeline compiler, sparse SDF layout, sculpt journal, residency decisions, generation and raymarching passes, picking, and export. Those parts would remain project-specific even if the underlying engine changed.

I developed both during the same graduation project. The standalone Aurora Engine case study covers the engine itself in more detail and reflects a slightly newer version than the one used at the end of this project.

Two systems worth a closer look

Make editable graphs safe to execute

The node system turns a visual, user-editable graph into a validated program. Generated types keep the editor, serialization, registration, and executor in agreement, while the compiler rejects broken connections before they can reach generation work.

Read the Node System deep dive

Update a planet without rebuilding it

The sparse SDF system combines brick allocation, ordered edits, spatial pruning, background planning, and GPU traversal. Together they limit regeneration and rendering to the parts of the volume that can actually matter.

Read the Sparse SDF deep dive

Sculpting and export

Sculpt strokes are stored as ordered union or subtraction operations instead of being baked irreversibly into voxels. Undo and redo can therefore change the active history, and a brick can be regenerated at another resolution by replaying the procedural program and only the edits that overlap it.

A sculpt changes the journal immediately; background planning and GPU generation update the affected sparse bricks.

For reusable procedural content, volume export stores the pipeline and sculpt history. For conventional asset pipelines, background CPU extraction samples the same result into an indexed GLB mesh. The full recording below shows node editing, live regeneration, sculpting, and export in one video.

The complete editor workflow, from procedural graph to sculpted and exported result.