Quick Start Guide
Let's get started with Shape-Z by creating a voxel box with the dimensions of 4x4x4 units and placing it at the origin. One unit (or tile) corresponds to a 1x1x1 cube in world space. By default Shape-Z uses a density of 40
, meaning:
- 1 unit = 40 × 40 × 40 = 64,000 voxels
- A shape of 4x4x4 units becomes 160 × 160 × 160 voxels
- That’s a total of 4,096,000 voxels
You can easily change the density, more on that later.
The Black
material is one of the 4 default materials of Shape-Z. Here, we are simply telling the system to apply the Black material to every voxel inside the box.
Shape-Z uses a math syntax similar to GLSL, but internally it operates entirely on a single language type: vec3
, which you can define as 4
, 4.0
, vec2(0, 1)
, or vec3(1, 2.0, .5)
.
For best performance, install the native version of Shape-Z. While the web version supports multi-threading, it is still significantly slower due to current WebAssembly limitations—such as the lack of SIMD and less efficient threading.
Shader like modeling
In the next example, we manually calculate the distance to a sphere at the center of the voxel box.
While Shape-Z offers many built-in tools to simplify tasks like this, it's helpful to understand that you can also write code much like a fragment shader.
The system variable local
defines the position of each voxel in local space, with the origin at the center of the voxel box.
This kind of free-style is very useful for procedural, noise based modeling. The rocks in the light house example were created this way.
Core modeling mechanics
Shapes define a working region (and often a coordinate system—e.g., Rect
is Cartesian, Disc
is polar). Shapes can be further subdivided by segments (e.g., Floor
, Left
, Right
), which establish a local domain and the convenience variables u
, v
, and d
.
In segments, u
(horizontal), v
(vertical), and d
(depth/extrusion) are given in segment-local world units, measured relative to the segment’s origin and active plane.
Because segments/nodes consistently provide u
, v
, d
in their local domain, modeling and patterning are independent of where they run. For example, a Bricks
pattern can be applied to any segment; on a Disc
, the shape exposes a polar domain so u
naturally follows the angle around the circle.
In the next example we create a very simple pattern on the Left
wall (a segment of the Rect
shape), by checking the values of u
, v
and d
.
In the upper half of the left wall we create a simple relief pattern. The Clear
instruction clears any voxel which may have been previously set. In the lower half we just set the left side of the wall to Black
and the right side to White
.
By being able to control the extrusion of the wall via the d
variable we have a powerful tool to shape the depth of segments. The d
variable always starts at 0 at the outside of the segment to the given depth
of the segment.
Try to replace 'Left' with any other sub-segment of Rect
, i.e. Back
, Right
, Front
, Floor
and Ceiling
. You will notice that the pattern will stay the same.
Patterns and Materials
In the next example we take things a step further and apply the Bricks
pattern—each with different parameters—to the Left and Back walls, as well as the Floor. Because patterns operate in the local (u, v, d)
domain of the active segment, the same pattern adapts automatically to each surface and orientation.
We also declare two materials: one dedicated to the left-wall bricks and one for the floor. Materials in Shape-Z follow a Disney/Principled BSDF model, so you can control albedo, roughness, metallic, IOR, transmission, and more. To introduce natural variation, we use the built-in hash
variable. When a pattern (e.g., Bricks
) executes, it assigns hash ∈ [0,1]
in a stable, per-cell manner (for example, per brick). You can use hash
to modulate color or micro-properties for believable randomness.
Other things to note: the floor uses an if_clear
block. Since Shape-Z already set voxels for the Left and Back walls—where the segments overlap—we don't want to overwrite those with floor voxels. if_clear
ensures that we only set voxels if the space is currently empty.
On the Back wall, we also place a shape
to clear a window-sized space in the middle of the wall. Shape placement always uses the current (u, v, d)
coordinates, but normalized to the segment's size. A value of 0
places the shape fully at the start of the segment, 0.5
centers it, and 1
places it fully at the end. This makes precise placement intuitive and consistent across different segment sizes.
On the Left
wall, we placed some patches of cement or color on top of the bricks—just to demonstrate how we can model volumes with real content layering and depth.
Distance Volumes — the 3-D side of Shape-Z
Shape-Z uses two modelling ideas:
Concept | What it draws | Typical nodes |
---|---|---|
Shapes | An extruded 2-D region (walls, floors). They bring their own u v d coords and can be subdivided with segments. | Rect , Disc , … |
Distance Volumes | A full 3-D solid dropped inside the current shape. They also hand you a normalised u v d so patterns scale automatically. | Sphere , Box , Cylinder , … |
How a distance block works
A distance node gives you a 0 → 1 local frame:
d
– runs along the axis (0 atfrom
, 1 atto
).u
,v
– span the cross-section at eachd
.profile_scale {}
– scales the section before the SDF (tapers, bulges).profile_offset {}
– indents/bulges after the SDF (grooves, panels).volume {}
– writes voxels wherever the (possibly deformed) SDF is inside.
There are also two helper variables:
sdf
– the raw signed distance (negative inside, positive outside).inside
– convenience alias for-sdf
(positive inside, zero on the surface).
Below is a tapered, grooved cylinder built with exactly those hooks:
We also use config instructions to set the background and raise the density to 60 (default is 40) to better see the profile of the cylinder.