---
# System prepended metadata

title: Making Worlds Feel Alive with Procedural Systems in Blender

---

# Making Worlds Feel Alive with Procedural Systems in Blender

## Abstract

This hands-on class is focused on progressively building a simple space traffic system, using proceduralism. The two main building blocks of this system are the spaceship generator and the traffic paths. The goal of the system is to provide a believable behavior for the ships, making the background of a scene feel alive.

The spaceship generator will use procedural geometry modifications to achieve a variety of sci-fi looking vessels, using common geometry manipulation techniques, and simple shapes using boolean operations.

The traffic paths will be a simulation driven particle system, exposing parameters such as density, speed, etc.

While the spaceship system will be used as a practical example, the concepts are more generally applicable to similar scenarios.

There is no requirement of previous experience with the Geometry Nodes system, while a base level familiarity with Blender is encouraged to follow along.

## Files

[Files are here.](https://drive.google.com/drive/folders/192oUAFUdoQRXgPXEu4dJAbJtnICpgiAm?usp=sharing)

## Shortcuts Cheatsheet

- Move selected nodes: `G`
- Viewer: `CTRL + SHIFT + LMB`
- Add node: `SHIFT + A` -> search
- Add node from socket: `LMB drag + let go` -> search
- Mute node: `M`
- Frame: `F`
- Rename: `F2`
- Add reroute node: `SHIFT + RMB drag`
- Cut links: `CTRL + RMB drag`
- Mute links: `CTRL + ALT + RMB drag`
- Toggle Maximize Editor: `CTRL + Spacebar`

## STEP by STEP guide

### I. Spaceship Generator

![spaceship_generator-target](https://hackmd.io/_uploads/rktoZGcDll.png)

#### 1. Base Layer

![image](https://hackmd.io/_uploads/HJHOfM5wxe.png)

![image](https://hackmd.io/_uploads/BymMefcPxx.png)

<details>
    
- scatter points on base plane (`Distribute Points on Faces`)
- create collection with set of base meshes
- instance base meshes on the generated points (`Collection Info`, `Instance on Points`)
    - enable `Separate Children` and `Pick Instance`
- merge instances into one mesh (`Mesh Boolean` - Union, Manifold)
- expose `Seed` as modifier input (drag link and search for `Group Input`)

</details>

#### 2. Rotate + Bisect

![image](https://hackmd.io/_uploads/Byyoyz9Pee.png)

<details>

- after Base Layer
- rotate randomly (`Transform Geometry`; `Random Value` - Vector)
    - use `Seed` input from modifier as `ID` to generate single value
- create cube mesh for intersection (`Cube` - size 200; `Transform Geometry` - `X = -100`)
- generate difference mesh ('Mesh Boolean' - Difference, Manifold)
- delete inside faces (`Delete Geometry` - Face; `Capture Attribute` - Face)
    - Capture a `True` boolean on the cube before intersectionand use the captured result as selection for deleting faces after

</details>

#### 3. Mirror

![image](https://hackmd.io/_uploads/H1WMkfcvxx.png)

<details>

- at the end of the node-tree
- flip mesh on X axis (`Transform Geometry` - `Scale = [-1,1,1]`)
- join with original (`Join Geometry`)

</details>

#### 4. Subtraction Layer

![image](https://hackmd.io/_uploads/rJWFefcPgl.png)

<details>

- after the Base Layer, before Rotate + Bisect
- scatter base meshes on base layer mesh (`Distribute Points on Faces`; `Instance on Points`)
    - use same instances as before
    - enable `Pick Instance` as before
- subtract from base layer mesh (`Mesh Boolean` - Difference, Manifold)
 
</details>

#### 5. Greeble

![image](https://hackmd.io/_uploads/HkOcCWqPle.png)

<details>

- after Rotate + Bisect
- extrude random faces (`Extrude Mesh` - Offset = 0; `Random Value` - Boolean, Probability = 0.5)
- scale extruded faces down (`Scale Elements` - Scale = 0.9)
    - `Top` as selection
- extrude again with random offset (`Extrude Mesh`; `Random Value`)
    - previous `Top` as selection
    - random value as `Offset Scale`
    - range negative to positive (e.g. 0.05)
- repeat whole process
    - add repeat zone
    - integrate geometry data flow into the repeat zone
    - use repeat iteration index as Seed for randomization
- don't use side faces for further extrusion
    - `Side` from 1st extrusion `Or` `Side` from 2nd extrusion
    - `Not`
    - `And`
    - pass result into new repeat output
    - make that repeat input `True` and pass into second `And` input
    
</details>

#### 6. Wires

![image](https://hackmd.io/_uploads/SJNyWzcDlx.png)

<details>

- after Rotate + Bisect in parallel to Greeble
- generate convex hull (`Convex Hull`)
- convert to curves (`Mesh to Curve`)
- create tubes from curves (`Curve to Mesh` - Scale = 0.002; `Curve Circle` - Resolution = 4)
    - circle as profile curve
- add sagging deformation
    - `Subdivide Curve` between `Mesh to Curve` and `Curve to Mesh` (Cuts = 20)
    - Deform using `Set Position`
    - `Spline Parameter` - `Factor` into `Float Curve` into `Combine XYZ` - `Z` into `Offset`
        - float curve points: `[[0,0], [0.5, 0.25], [1, 0]]`
    - `Scale` the offset vector by `-0.5`
- turn each edge into its own curve (`Duplicate Elements` - Edge)
    - use a random selection (`Random Value` - Boolean, Probability = 0.5)
- `Scale` the sagging offset vector by `Spline Length`
- assign different materials to main and wires geometry
- join with main mesh (`Geometry to Instance`)
    
</details>

### II. Spaceship Zoo

![image](https://hackmd.io/_uploads/ryO1Bv9Dll.png)

<details>

- create `Grid`
- generate spaceship for each point of the grid
    - add `For Each Element` zone
    - connect grid to zone input
    - add spaceship generator node-group in zone and connect to group geometry input and zone geometry ouput
    - connect zone index to seed
- move each to its grid point position
    - convert `Geometry to Instance`
    - `Transform Geometry` of instance
    - add `Position` to zone inputs
    - use position of the point inside the zone for the translation
- make seed dependant on modifier input
    - add `Hash Value` node to zone `Index`
    - expose `Seed` input to group inputs
- name each spaceship geometry by its used seed
    - convert hashed `Value to String`
    - `Set Geometry Name` from that string
    - `Join Strings` with new `String` ('Spaceship ')
- store used seed as attribute
    - pass hash result as attribute on zone output geometry
    - set attribute domain to `Instance` in zone node properties
    - add `Store Named Attribute` (Integer, Instance) outside of zone
    - connect hash attribute to value
    - give attribute name 'seed'

</details>
    
### III. Spaceship Swarm

![spaceship_swarm-target](https://hackmd.io/_uploads/Sk064qkdle.png)

#### 0. Starting Curve

![image](https://hackmd.io/_uploads/Bkc2ock_gl.png)

<details>
    
- create curve
- set cyclic
- set resolution to `64`
    
</details>

#### 1. Create Points

![image](https://hackmd.io/_uploads/BkKbm5kuxl.png)

<details>
    
- `Points` node
    - expose `Count`
- randomize `Set ID`
    - `Index` into `Hash Value`
- `Sample Curve` for random position per point
    - `Random Value` into `Factor`
    - `Position` into `Points` `Position`
    - expose `Seed`
    
</details>

#### 2. Instancing

![image](https://hackmd.io/_uploads/r1r9kjJ_eg.png)

<details>
    
- get input instances
    - `Object Info` of spaceship object
- extract individual spaceship instances
    - `Separate Components` - `Instances`
- reset instance positions
    - `Set Position` to `Vector` [0,0,0]
- `Instance on Points` - `Pick Instances` = `True`
    - `Align Rotation to Vector` - `Y` into `Rotation`
    - use sampled curve `Tangent` as alignment `Vector` (for now)
    
</details>

#### 3. Basic Simulation Setup

![image](https://hackmd.io/_uploads/HJmurqkdex.png)

<details>

- add `Simulation` zone
- add `Set Position` node
- add `Velocity` vector to simulation
- `Scale` velocity by `Delta Time` and use as `Offset`
- accelerate every frame with constant force
    - `Add` to velocity and pass it to the simulation output
    - `Scale` constant `Vector` by `Delta Time` and plug into `Add`
    
</details>

#### 4. Curve Sampling

![image](https://hackmd.io/_uploads/H1bIbcJOxe.png)

<details>

- `Sample Index` - `Vector` on curve
- `Curve to Points` - `Evaluated`
- `Sample Nearest` as `Index` for `Sample Index`
- `Tangent` as `Value` input
- duplicate to sample `Position` as well
    
</details>

#### 5. Speed Alignment

![image](https://hackmd.io/_uploads/ByMzr9kOel.png)

<details>

- `Scale` sampled curve tangent randomly
- `Random Value` between `20` and `50` as different target speed per point
- `Mix` (`Factor` = `.1`) into `Velocity` to align to target speed along curve
    
</details>

#### 6. Curve Attraction

![image](https://hackmd.io/_uploads/SJae89J_el.png)

<details>

- `Subtract` `Position` from Nearest Curve Position
- `Scale` by its `Length` to the `Power` of `2`
- use result as acceleration force
    
</details>

#### 7. Evade Neighbors

![image](https://hackmd.io/_uploads/H1By8qJdel.png)

<details>

- duplicate 'Curve Attraction' setup
- instead of nearest curve tangent, use `Evaluate at Index` of `Position` at `Index of Nearest`
- invert strength falloff
    - `Divide` `25` by (existing) `Length`
- `Add` result to total forces
    
</details>

#### 8. Clamping

![image](https://hackmd.io/_uploads/S10THqkdll.png)

<details>

- `Normalize` total force vector
- `Scale` by its `Length` clamped by `Smooth Minimum` with `100`
    
</details>