INSODIMENSIONStudios
BiomesReference

PCG nodes

Reference for the six custom PCG nodes Agentic Biomes adds - pins, every setting with its default and range, exact behaviour, and which shipped graphs use each node.

PCG nodes

Agentic Biomes adds six nodes to the PCG graph editor. Five of them filter or reshape point data (height bands, curvature, cliff faces, fog). The sixth, Biome Sampling Domain, bounds the sampling area of a biome region. They live in the AgenticBiomes runtime module.

Open a PCG graph, right-click, and search for the node title. The palette category is the engine's name for the node type: Point Ops for the five point nodes and Spatial for Biome Sampling Domain.

NodePalette titleCategoryUsed by shipped graphs
UPCGHeightGradientSettingsHeight GradientPoint OpsSG_AT_EffectScatter, SG_S_HeightGradientCpp
UPCGCurvatureFilterSettingsCurvature FilterPoint OpsSG_AT_CurvatureScatter, SG_S_CurvatureFilter
UPCGCliffPlaceSettingsCliff PlacePoint OpsSG_AT_Cliffs_Simple, SG_Sampler_CliffWalls_LS, SG_Sampler_CliffWalls_Landscape
UPCGCliffHeightSettingsCliff HeightPoint Opsnone
UPCGFogPlacementSettingsFog PlacementPoint OpsSG_AT_FogScatter
UPCGBiomeSamplingDomainSettingsBiome Sampling DomainSpatialSG_AT_TerrainSurface

The shipped graphs are in /AgenticBiomes/PCG/Generators/ and /AgenticBiomes/PCG/SubGraphs/.

In the tables below, the first name is the label Details shows (the engine humanizes the C++ name; for a bool, bUseFogPlacement shows as Use Fog Placement). The C++ name is in backticks. Every setting on the five point nodes can also be driven from a graph parameter through its override pin.


Behaviour shared by the point nodes

  • Pins. Each point node has one input pin, In, and one output pin, Out, both point data. Height Gradient, Cliff Height, Cliff Place and Fog Placement also accept spatial data that can be converted to points. Curvature Filter only accepts data that is already points. An input the node cannot use is skipped, and most nodes log an Error for it.
  • Empty input. An input with zero points is passed through unchanged by every node except Curvature Filter, which produces no output for it.
  • Execution. Cliff Place and Fog Placement run on the main thread only. The other point nodes are not restricted to it.
  • Deterministic thinning. Where a node thins points by probability, it compares the probability with a number derived from the point's world position: the X, Y and Z coordinates are rounded to whole centimetres, hashed, and reduced to 16 bits. The same point at the same position always gets the same answer, so a regeneration does not reshuffle the scatter. The values are quantised: positions less than a centimetre apart can land on the same number, and there are 65,536 levels.
  • Terrain-only traces. Cliff Place and Fog Placement trace against the level's terrain, on either backend (Landscape or MeshTerrain), and ignore PCG-spawned scatter. Results do not depend on which generator ran first. When the terrain cannot be resolved, both log an Error with the reason and emit no points rather than pass unfiltered points on.

Height Gradient

Thins, scales or moves points according to how high they sit, relative to the other points in the same input.

How it works. The node finds the lowest and highest Z in the input and maps each point's Z to a height between 0 and 1. Points outside HeightLow to HeightHigh, plus the Falloff margin on each side, get density 0. Inside the band, density follows the chosen curve from DensityAtBase (at HeightLow) to DensityAtTop (at HeightHigh), and never drops below MinDensity. In the two falloff margins, density is DensityAtBase or DensityAtTop multiplied by a smoothstep ramp that reaches 0 at the outer edge. MinDensity does not apply in the margins.

With bRemoveZeroDensity on, points with density 0 or less are removed, and points with density below 1 are kept with a probability equal to their density (deterministic, see above). Surviving points get that density, limited to 0 to 1, written to $Density.

Heights are normalised over the input the node receives, not over the whole map. In a partitioned or tiled graph, each input set has its own lowest and highest Z, so the same terrain can be thinned differently per tile. If every point has the same Z, the input passes through unchanged. With the defaults (HeightLow 0, HeightHigh 1) the band spans the whole input, so Falloff has no visible effect until you narrow the band.

Settings

SettingTypeDefaultRangeMeaning
Use Height Gradient bUseHeightGradientbooltrueMaster switch. When off, all points pass through unchanged.
Height Low HeightLowfloat00 to 1Bottom of the band.
Height High HeightHighfloat10 to 1Top of the band. If it is not greater than HeightLow, the node logs a Warning and passes the input through unchanged.
Curve Type CurveTypeenumLinearShape of the gradient inside the band. See the curve table.
Density At Base DensityAtBasefloat0Density at HeightLow.
Density At Top DensityAtTopfloat1Density at HeightHigh.
Falloff Fallofffloat0.20 to 0.5Width of the smoothstep margin outside the band, in normalised height. 0 gives a hard cutoff.
Min Density MinDensityfloat0.10 to 1Floor for density inside the band.
Invert bInvertboolfalseReverses the gradient direction within the band.
Terrace Count TerraceCountint42 to 16Number of shelves. Only editable when Curve Type is Terrace.
Terrace Sharpness TerraceSharpnessfloat1.00.5 to 8.0Narrowness of each shelf peak. Only editable when Curve Type is Terrace.
Remove Zero Density bRemoveZeroDensitybooltrueRemove points with density 0 or less, and thin the rest by density. When off, no point is removed by this node and points outside the band keep density 0.
Apply Scale bApplyScaleboolfalseMultiply each surviving point's scale by a height-based factor.
Scale At Base ScaleAtBasefloat1.00.01 to 5Scale factor at HeightLow. Needs Apply Scale.
Scale At Top ScaleAtTopfloat1.00.01 to 5Scale factor at HeightHigh. Needs Apply Scale.
Apply Offset bApplyOffsetboolfalseMove each surviving point by a height-based vector.
Offset At Base OffsetAtBasevector0, 0, 0Offset at HeightLow. Needs Apply Offset.
Offset At Top OffsetAtTopvector0, 0, 0Offset at HeightHigh. Needs Apply Offset.

Details groups these under Height Gradient, Height Scale and Height Offset. Scale and offset use the same curve as density, and inside the falloff margins they blend from no change (scale 1, offset zero) to the base or top value. With Invert on, the base and top values swap in the margins and the band parameter is flipped inside the band.

Curve types

T is the position inside the band, 0 at HeightLow and 1 at HeightHigh.

CurveValueEffect
LinearTEven gradient.
EaseInT squaredSparse at the base, concentrated toward the top.
EaseOut1 minus (1 minus T) squaredDense at the base, thinning toward the top.
SCurvesmoothstep of TSmooth transitions at both ends.
ExponentialT cubedVery sparse at the base, steep toward the top.
Bell4 times T times (1 minus T)Peak in the middle, sparse at the edges.
TerraceBell shape repeated TerraceCount times, raised to TerraceSharpnessRepeating shelves. Higher sharpness gives narrower shelves.

Curvature Filter

Keeps points that sit where the terrain bends: hilltops, ridge lines, terraces. Use it to scatter things only on curved ground.

How it works. For each point the node traces down at the point and at four neighbours, north, south, east and west, each FeatureScale away. If any of the five traces misses, the point is dropped. Curvature is the absolute difference between the average neighbour height and the centre height, divided by FeatureScale, clamped to 0 to 1. A point is kept when its curvature is at least Threshold. With bWriteDensity on, the curvature is written to the point's density, so a later density filter can use it.

Settings

SettingTypeDefaultRangeMeaning
Feature Scale FeatureScalefloat30050 to 5000Distance in cm from the point to each neighbour sample. Small values pick up tight bends, large values broad hills.
Threshold Thresholdfloat0.050 to 1Minimum curvature to keep a point. 0 keeps every point that has all five traces.
Write Density bWriteDensitybooltrueWrite the curvature to point density. When off, density is left unchanged.

All three are in the Curvature Filter category.

This node does not use the terrain-only trace. It casts a plain world line trace on the World Static channel with complex collision, from 50,000 cm above to 50,000 cm below the height of each sample. Anything with collision on that channel, including meshes spawned by other graphs that ran earlier, can be hit instead of the ground. It needs a world; without one it logs an Error and returns no output.


Cliff Place

Measures how tall the cliff face is at each point, drops points on cliffs outside a height range, and turns the survivors to face outward from the rock.

How it works. For each point the node traces the terrain from 1,000 cm above to 5,000 cm below to get the surface normal. Points with no terrain hit are dropped. It then walks along the horizontal direction of the normal in 200 cm steps, up to SearchRadius in each direction, tracing the terrain at each step. A walk stops early when the surface becomes nearly flat (normal Z above 0.95). The cliff height is the absolute Z difference between the highest and lowest point reached. Points shorter than MinCliffHeight or taller than MaxCliffHeight are dropped.

With bAlignToSurface on, each kept point is snapped to the terrain hit and rotated so its X axis points out of the cliff, with pitch set to 0. LocationOffset is applied in that cliff-face frame, then a random rotation between RotationMin and RotationMax is composed in the same frame, and finally YawOffset and RollOffset are added. The random rotation is seeded from the point's rounded position, so it is the same every run. Scale is kept. With bAlignToSurface off, kept points keep their original transform and only the height filter applies.

Settings

SettingTypeDefaultRangeMeaning
Search Radius SearchRadiusfloat2000at least 200Longest horizontal walk along the cliff face, in cm. Larger values measure taller cliffs but cost more traces. The tooltip suggests 1000 to 3000.
Min Cliff Height MinCliffHeightfloat0at least 0Shortest cliff to keep, in cm.
Max Cliff Height MaxCliffHeightfloat100000at least 0Tallest cliff to keep, in cm.
Align To Surface bAlignToSurfacebooltrueRotate points to the cliff face.
Rotation Min RotationMinrotator0, 0, 0Lower bound of the random rotation, in degrees, in the cliff-face frame.
Rotation Max RotationMaxrotatorpitch 0, yaw 360, roll 0Upper bound of the random rotation. The default spins each point randomly around its yaw.
Yaw Offset YawOffsetfloat0Extra yaw after alignment, in degrees.
Roll Offset RollOffsetfloat0Extra roll after alignment, in degrees.
Location Offset LocationOffsetvector0, 0, 0Offset in the cliff-face frame, in cm. X runs along the outward normal, so a negative X pushes the point into the rock. Y runs along the face, Z is up.

SearchRadius is in the category CliffPlace and the two height limits are in CliffPlace|Height Filter. Align To Surface and the five rotation and offset settings are all in CliffPlace|Rotation; those five are editable only when Align To Surface is on.

Failure behaviour

  • If the terrain cannot be resolved, the node logs an Error and emits nothing. It fails closed on purpose, because passing the input on would scatter cliff-only meshes over flat ground.
  • If the PCG context has no world, the node logs an Error and passes its input through unchanged.

Cliff Height

Filters points by the height of the cliff they belong to, without any traces.

How it works. The node builds a 3D spatial hash with cells SearchRadius wide. Two points are connected when they are within SearchRadius of each other in 3D, and connected points form one group (union-find). The group's cliff height is its highest Z minus its lowest Z, and every point in the group shares it. Points in a group whose height is below MinCliffHeight or above MaxCliffHeight are removed.

Use several graph instances with different height ranges to put small rocks on ledges and large rocks on big walls. The node only filters. It does not write the height to an attribute.

Settings

SettingTypeDefaultRangeMeaning
Search Radius SearchRadiusfloat2000at least 200Distance in cm within which two points are treated as the same cliff.
Min Cliff Height MinCliffHeightfloat0at least 0Groups shorter than this are removed.
Max Cliff Height MaxCliffHeightfloat100000at least 0Groups taller than this are removed. Set very high to disable.

Search Radius is in the category Cliff Height, and the two height limits are in Cliff Height|Filter.

No shipped graph uses Cliff Height; Cliff Place does the same height filtering and adds rotation. The Details tooltip on SearchRadius talks about neighbours in an XY radius, but the node measures distance in 3D, so points on very different levels of the same wall can fall in different groups.


Fog Placement

Decides where fog cards go, from the shape of the terrain, the height, or both.

How it works. The node first finds the lowest and highest Z of the input and maps each point to a height from 0 to 1. Points outside HeightMin to HeightMax are dropped. For each remaining point it traces NumSamples neighbours spaced evenly on a circle of radius AnalysisRadius, and computes the topographic position index, TPI: the point's Z minus the average Z of the neighbours that were hit. At least NumSamples divided by 2 (rounded down) of the samples must hit terrain, otherwise the point is dropped (this removes points near the terrain edge). A negative TPI means the point sits in a bowl or valley, a positive one that it sits on a ridge.

Probability depends on the mode:

ModeProbability
Valley1 / (1 + exp(TPI * TPISteepness * 1000)). About 0.5 at TPI 0, approaching 1 for negative TPI.
Orographicexp(-(h - CloudBaseHeight)^2 / (2 * CloudBandWidth^2)), where h is the normalised height. A bell around CloudBaseHeight.
CombinedThe larger of the two. This is the default.

Points with probability below MinProbability are removed. With bRemoveLowProbability on, the rest are thinned with the deterministic position hash, so a point with probability 0.5 survives about half the time. Survivors get the probability written to $Density. If WindStrength is above 0, each survivor is moved in X and Y along the normalised WindDirection by WindStrength times its probability.

With the default TPISteepness, the valley probability swings from near 1 to near 0 within a couple of centimetres of TPI either side of zero, so in practice it acts as a bowl-or-ridge test. Lower the steepness to widen the transition.

TPIThreshold is declared, shown in Details and logged, but the probability calculation does not read it. Changing it has no effect on the result. Use TPISteepness, MinProbability and the height band instead.

Settings

SettingTypeDefaultRangeMeaning
Use Fog Placement bUseFogPlacementbooltrueMaster switch. When off, all points pass through unchanged.
Mode ModeenumCombinedValley, Orographic, CombinedHow probability is computed.
Analysis Radius AnalysisRadiusfloat5000at least 500Radius of the neighbour circle, in cm. Larger finds broader valleys.
Num Samples NumSamplesint84 to 16Neighbour traces per point.
TPI Threshold TPIThresholdfloat-500Not used by the calculation, see above.
TPI Steepness TPISteepnessfloat0.0020.0001 to 0.01Steepness of the valley sigmoid.
Cloud Base Height CloudBaseHeightfloat0.60 to 1Centre of the orographic band, as a fraction of the input's height range.
Cloud Band Width CloudBandWidthfloat0.150.01 to 0.5Width of the orographic band, in the same units.
Height Min HeightMinfloat00 to 1Points below this normalised height are removed.
Height Max HeightMaxfloat10 to 1Points above this normalised height are removed.
Min Probability MinProbabilityfloat0.30 to 1Points below this probability are removed.
Remove Low Probability bRemoveLowProbabilitybooltrueThin points by probability, using the position hash.
Wind Direction WindDirectionvector 2D1, 0Direction fog is pushed, in the XY plane. Normalised internally.
Wind Strength WindStrengthfloat0at least 0Maximum displacement in cm. 0 turns the wind off.
Trace Start Offset TraceStartOffsetfloat1000at least 0Height above each sample point at which its trace starts, in cm.
Trace Distance TraceDistancefloat15000at least 100Length of each downward trace, in cm. It must reach below the terrain.
Landscape Only bLandscapeOnlybooltrueAccept only terrain hits for the neighbour heights, on either backend. When off, any other world geometry counts too; PCG-spawned scatter is ignored either way. The name is kept so existing graphs keep working.

Details groups these under the categories Fog Placement, Fog Placement|TPI, Fog Placement|Orographic, Fog Placement|Filtering, Fog Placement|Wind and Fog Placement|Trace. Neighbour traces use the Visibility channel.

Failure behaviour

  • With Use Fog Placement off, or with an input whose points all share one Z, the input passes through unchanged.
  • If the PCG context has no world, the node logs an Error and passes its input through unchanged.
  • If the terrain cannot be resolved, the node logs an Error and emits nothing.

Biome Sampling Domain

Gives a biome region's PCG graph a stable footprint and a bounded sampling volume. Biome Build stamps each region with a sampling domain and a proven scatter support margin, and this node reads them. You normally meet it inside the shipped subgraph SG_AT_TerrainSurface rather than adding it yourself.

Pins

PinDirectionTypeNotes
IninputSplineRequired. Exactly one spline: the footprint rectangle.
OutoutputSplineThe footprint, rebuilt to the stamped domain when the region has one.
BoundsoutputVolumeThe volume native sampling should stay inside.

The node has no settings.

What it does

  1. It finds the original execution source. That must be a biome region (AAgenticBiomeRegion) or a non-partitioned volume.
  2. If the region has a finite SamplingDomainBounds, it rewrites the four control points of the input spline to a rectangle centred on the domain, with the domain's extent. The corner order is (+X, +Y), (+X, -Y), (-X, -Y), (-X, +Y).
  3. It builds the Bounds volume. If the region has a sampling domain, its scatter support is resolved (bScatterSupportResolved) and its margin ScatterSupportMarginCm is zero or more, the volume is the execution bounds expanded by that margin. Otherwise the volume is the bounds of the (possibly rebuilt) spline.

The region's SamplingDomainBounds, bScatterSupportResolved, ScatterSupportMarginCm and ScatterSupportSource are read-only values under the category Biome|Provenance in the region's Details.

Input rules

The input must be a closed spline of exactly four linear points forming a rectangle in the XY plane: finite values, equal opposite edges, perpendicular edges, constant Z. For a stamped region the corners must also be in the order given above. The node does not reorder control points.

Refusals

The node is not cached and runs on the main thread. Each refusal below logs an Error and cancels the execution of the graph.

RefusalMeaning
Missing execution sourceThere is no valid execution source, or its original source cannot be resolved.
Unsupported sourceThe source is not a biome region or a non-partitioned volume, or it is a partitioned or local source without a stamped region.
Invalid domainThe region's sampling domain is not finite, or a partitioned source has none. Rebuild the biome map.
Invalid supportA partitioned source has no valid resolved scatter support margin, or a region marked as resolved has a negative or non-finite margin. Rebuild, or use map-wide non-partitioned generation.
Wrong inputIn does not carry exactly one spline.
Bad footprintThe spline is not the rectangle described above, or the corner order is wrong for a stamped region.
Bad metadata keysThe footprint's spline metadata keys do not match its control points.
Bad execution boundsThe support margin is used but the execution source has no finite bounds.
Bad sampling boundsThe resulting volume is not finite, or has zero height.

Limits

  • Curvature Filter, Cliff Place and Fog Placement trace the world, so they cost traces per point (one to five for Curvature Filter, up to NumSamples for Fog Placement, and a walk of traces for Cliff Place). Cliff Height uses no traces. The plugin source contains no measured timings, and none are given here.
  • Height Gradient and Fog Placement normalise height over the points they receive. Feed them whole sets if you want results that do not vary with tile boundaries.

Need help? Join the Insodimension Discord. Related pages: Terraformer, Biome asset, Runtime ground cover.