Geometry Nodes For TAs
Geometry Nodes lets you build a modelling process that responds to new inputs. Geometry passes through nodes, attributes carry data, and exposed controls let an artist adjust the result. We’ll use a scatter tool to look at how those pieces fit together.
On this page
The Procedural Mindset Fields Vs Attributes Build: The Scatter Tool The Artist Interface Getting It Into An EngineThe Mindset Shift
Destructive modelling edits the thing. Procedural modelling edits the recipe. A Geometry Nodes tree is a recipe: geometry enters, each node transforms it, geometry exits - and because the recipe is live, changing an early step (the input curve, the density value) re-cooks everything downstream instantly. The payoff is the same as in Houdini: when level design moves the canyon, you move a curve, not two hundred rocks.
The corollary that trips artists over: selection basically doesn't exist here. You can't grab "those three points." Instead you describe which points qualify - "points where the slope is under 30 deg" - and the description keeps working when the terrain changes. Procedural selection is a rule, not a click.
Fields Vs Attributes - The Two-Sentence Version
An attribute is data stored on geometry: every point carries a position, maybe a colour, maybe a density float you invented. A field (the diamond sockets) is a question asked of every element at once: "what's your position?", "what's your index?", "what does the noise texture say at your location?" - evaluated per-point wherever you plug it in.
The relationship: fields compute, attributes remember. A field is a formula; capturing or storing it (Capture Attribute / Store Named Attribute) freezes the answer onto the geometry so a later node - or the exporter, or a shader - can read it back. If you know Houdini: fields ~= what a wrangle computes on the fly; stored attributes ~= @attrs. If you don't: a field is a spreadsheet formula, an attribute is paste-values.
Build It: A Scatter Tool Worth Keeping
A scatter tool is a useful first exercise because its inputs and results are easy to inspect. New Geometry Nodes modifier on your terrain, then:
Group Input (terrain) +- Distribute Points on Faces [Poisson Disk, Density Max, Seed] +- density <- Noise Texture -> Map Range (clumpy, not uniform) +- density <- Normal.Z < threshold ? 0 : 1 (nothing on cliffs) +- Instance on Points +- instance <- Collection Info [rocks collection, Separate Children + Pick Instance] +- rotation <- Align Euler to Vector (surface normal) + Random Euler Z +- scale <- Random Value (0.7-1.4) [same Seed input] +- Realize Instances? - NO (see export section) +- Group Output
Read the spine and notice: every art-direction lever is a field feeding density or a random value with a seed. Clumping is a noise texture; keep-off-the-cliffs is a question about the normal; variety is a collection of rocks picked per-instance. Nothing here is rock-specific - swap the collection and it scatters trees, debris, or mushrooms. That's the tell of a good procedural tool: the nouns are replaceable.
The Artist Interface Is The Actual Product
Select your scatter nodes -> Ctrl+G to make a group -> expose sockets in the N-panel. What you expose is a design decision, and the discipline is Houdini's HDA discipline exactly:
- Expose five things, not twenty-five: Density, Seed, Scale Range, Slope Limit, and the Collection. Add more controls when there’s a clear use for them.
- Name in artist, not in node: "Clumping" beats "Noise Texture W Remap Factor."
- Set defaults that look good on the demo terrain. Useful defaults help an artist understand the tool before adjusting it.
- Always expose Seed. A seed gives the artist a repeatable way to try another arrangement - see the same rule in our Python snippets (seeded scatter).
Mark the group as an asset (right-click -> Mark as Asset) and it appears in the Asset Browser for the whole team - the team can reuse the node group without needing a Python add-on.
Getting The Result Into An Engine
The engine needs an exported representation of the Geometry Nodes result. Three exits, in order of preference:
- Export placements, not geometry. The scatter's real product is transforms. Store position/rotation/scale, export a lightweight point cloud or a CSV (via bpy), and instance the rocks engine-side - Unreal ISMs or foliage, Unity prefab instancing. 500 rocks as instances: one mesh in memory. Realised: 500 meshes' worth of vertices in your file and your streaming budget.
- Realize Instances -> one mesh - legitimate for small dressing clusters (a barrel pile) where per-instance engine handling is overkill. Watch the poly count; realise is where "procedural" quietly becomes "800k-triangle prop."
- Bake attributes into exports: Store Named Attribute writes into UVs or vertex colours, which survive FBX/glTF - procedural moss masks and gradient data arriving in your engine shader for free. This is the bridge between this page and shader work.
A curve-driven cable tool is a useful example: expose sag, clamp spacing, and a seed, then test it against a hand-built cable run. Measure both the initial placement time and the time needed after a layout change. That gives the team a practical comparison, rather than assuming procedural generation will save time in every case.
