Morphon SDF editor with blended and subtractive primitives
github.com/NarinderBrar/Morphon · real application screenshot
Project 6 · Open source · 2026

Morphon

A Vulkan SDF modelling experiment: analytic primitives, smooth blending and live subtractive editing without rebuilding a triangle mesh.

C++20VulkanGLSLDear ImGuiSDF ray marching
5analytic primitive types
64 Bper object record
256current object limit
128GPU march steps max
What I built

Procedural modelling inside a real editor

01Five SDF primitives

Box, sphere, torus, cylinder and cone/pyramid evaluated analytically in GLSL.

02Solid + void

Smooth-union additive shapes and subtractive shapes that cut live holes.

03Selection

CPU ray-march picking, single selection, marquee multi-selection and hide/show state.

04Editing

Axis-constrained move gizmo, property editing and direct box-face dragging.

05Placement preview

Shape-aware wire preview, snap-to-grid and a solid/void mode before placement.

06Procedural shading

Finite-difference normals, two lights, soft shadows, AO, grid and fog.

07Vulkan foundation

Swapchain, descriptors, command buffers, fences and runtime GLSL compilation.

08Rotate + scale

Buttons and gizmo meshes exist; manipulation is not wired through yet.

09Intersection

The UI exposes it, but the current apply path behaves as subtraction.

Architecture

CPU interaction, GPU field evaluation

ImGui + inputtools · camera · props CPU SDF mirrorpick · place · drag Editor stateobjects · selection UBO object SSBO full-screen triangle3 generated vertices ray_march.fragfield → hit → shade gizmo subpassraster mesh overlay ImGui subpasseditor chrome
The procedural surface has no model vertex buffer. The separate raster path exists only for editor gizmos.
Architecture decisions

What I chose, and what it costs

DecisionAlternativeReason / trade-off
Analytic SDF objectsTriangle meshes + CSGLive booleans and blending with parameter changes; per-pixel field evaluation is expensive
Fragment ray marchingCompute + output imageSmall direct prototype; compute would give more explicit scheduling and tiling control
CPU SDF mirrorGPU ID/readbackImmediate world hit without synchronization; duplicated rules can drift
SSBO object arrayOne draw per objectOne full-screen draw evaluates the whole scene; currently scans up to 256 records
Raster gizmosSDF gizmosPrecise conventional handles, separate from modelling semantics
Runtime glslangOffline-only SPIR-VFast shader iteration for a tool; adds startup and dependency cost
Feature · sphere tracing

The distance field chooses every safe step

ray origin step = scene distanced < 0.002 → hit march loopp = origin + direction × tt += scene(p) · max 128 iterations
A conservative distance field guarantees the ray does not jump through the surface. The scene function is the hot path.
Feature · field composition

Booleans are arithmetic, not topology edits

unionmin(a, b) subtractmax(a, −b) smooth unionsmooth-min(a, b, k)
Morphon implements union/smooth union and subtraction. True intersection is still unfinished in the editor path.
GPU memory contract

One object = four aligned 16-byte groups

bytes 0–15 · metatype · primitiveparam1 · param2 bytes 16–31 · posx · y · zhidden bytes 32–47 · rotrx · ry · rzshape field / pad bytes 48–63 · scalesx · sy · szpad 64 bytes · static_assert 16-byte SSBO header + up to 256 contiguous records
The C++ structure and GLSL record both map to four vec4-sized groups. The static assertion catches accidental CPU-side drift.
Honest assessment

Strong prototype, clear next bottlenecks

0 mesh

Live procedural booleans

Moving a primitive updates 64 bytes; there is no topology rebuild.

1 draw

Full-screen scene

One generated triangle launches the field evaluation.

cache

Pointer-driven CPU query

Placement ray march reruns only when its inputs change.

O(P·S·N)

Current scaling limit

Pixels × march samples × objects; add bounds/BVH before growing the scene.

parity

Unify CPU and GPU rules

Picking must apply the same transforms and operations as rendering.

WIP

Finish exposed tools

Rotate, scale and true intersection need real interaction semantics.

No frame-time improvement is claimed: the repository contains architecture evidence, but no controlled benchmark.