Skip to content

Normal & Surface Nodes

The Normal category turns a height map into the surface data a renderer needs: slope, curvature, occlusion, flow direction and roughness. Every node here reads its input as height (as brightness, except Normal from Height, which reads the red channel), and every one wraps its sampling at the texture border, so a tiling input produces a tiling result.

Type id: normal_from_height

Converts a grayscale height map into a tangent-space normal map, encoding surface direction into the red, green and blue channels. This is the node you reach for whenever a height chain needs to drive lighting rather than displacement.

Inputs

  • Height (grayscale, required): the height field to read slopes from. A color map connects, but only its red channel is read; put a Grayscale node in front if you want its brightness instead.

Outputs

  • Output (color): a tangent-space normal map.
ParameterTypeDefaultRange / OptionsNotes
StrengthFloat4.00.0 to 32.0Slope multiplier. At 0 the map is dead flat; higher values exaggerate relief. Calibrated against a 1024 px result, so the same value reads the same at any output size.

The slope is measured over a stencil that widens with resolution, one texel at 1024 and four at 4K, so a large bake reads the shape rather than the dither baked into its input. A 4K normal map off a smooth height field comes out clean instead of sparkling with grain.

There is no Mask input, and no green-channel flip here. Use Normal Adjust for that.

Type id: curvature

Reads a height (or normal) map and reports where the surface bulges out and where it cuts in. It is the source of most edge-wear and grime masks: wear rides the convex peaks, dirt pools in the concave cavities.

Inputs

  • Height (any texture, required): the surface to measure. Color inputs are reduced to brightness first.

Outputs

  • Output (grayscale): the curvature response for the selected mode.
ParameterTypeDefaultRange / OptionsNotes
StrengthFloat8.00.0 to 64.0Scales the response. Low values isolate only the sharpest transitions; high values pick up gentle undulation too. Resolution-independent.
ModeChoiceCurvatureCurvature, Cavity, ConvexityCurvature is signed, with mid-gray meaning flat. Cavity keeps only the concave half, rescaled to fill the full black-to-white range so it drops straight into a multiply. Convexity is the mirror: ridges and edges only.

No Mask input.

Type id: ao_from_height

One sampling walk over a height map that produces ambient occlusion, thickness and a bent normal on three separate output ports. Pick the one you need straight off the node. Because all three come from the same walk they can never disagree about radius, which is the usual cause of a bent normal that lights wrong against its own AO.

Inputs

  • Height (any texture, required): the height field to sample.

Outputs

  • Occlusion (grayscale): classic ambient occlusion, dark where the neighborhood stands above the point.
  • Thickness (grayscale): how enclosed the point is, sampled at double the radius. Bright in troughs with material all around, dark on exposed ridges; drives subsurface and translucency masks.
  • Bent Normal (color): the average unoccluded direction encoded as a normal map, so cavities self-shadow correctly when lit along it.
ParameterTypeDefaultRange / OptionsNotes
RadiusFloat0.050.001 to 0.25Sampling distance as a fraction of the texture. Small values give tight contact shadows; large values give broad soft shading. Thickness reaches twice as far for the same setting.
StrengthFloat1.00.0 to 4.0How deep the occlusion goes, how bright thickness reads, and how far the bent normal tilts. At 0 the result is unoccluded / flat.
AngleFloat270.00.0 to 360.0Incoming direction, in degrees. Has no effect on any of this node’s three outputs.
SpreadFloat60.01.0 to 180.0Cone half-width, in degrees. Has no effect on any of this node’s three outputs.

No Mask input. Sampling density follows Radius, up to 10 rings of 32 taps, so widening the radius adds samples instead of spreading the same few further apart. Each pixel rotates the whole pattern and jitters each ring’s radius within its band, so what error is left reads as fine grain rather than as directional banding or concentric rings around every bump.

Type id: pocketing

Occlusion restricted to a single incoming direction: where light pools from a chosen angle, where rain would fall, where dirt would settle on upward faces. Sweeping the Angle is also how you extract multi-angle lighting information from one height map.

Inputs

  • Height (any texture, required): the height field to sample.

Outputs

  • Output (grayscale): occlusion seen only from the chosen cone; bright where that direction is open.
ParameterTypeDefaultRange / OptionsNotes
RadiusFloat0.050.001 to 0.25Sampling distance as a fraction of the texture.
StrengthFloat1.00.0 to 4.0How dark the occluded areas become. At 0 the output is uniformly open.
AngleFloat270.00.0 to 360.0The direction occlusion is measured from, in degrees.
SpreadFloat60.01.0 to 180.0Half-width of the cone around Angle. Narrow gives sharp shafts, wide gives soft pooling.

No Mask input. Directions outside the cone are ignored entirely rather than counted as open, so widening the cone shifts the result instead of uniformly darkening it. The cone edge is feathered by half the spacing between samples, which keeps a narrow Spread continuous instead of breaking into salt-and-pepper where a pixel happens to catch no sample inside the cone.

Type id: flow_map

Turns a height map or mask into a direction field, encoded in red and green with mid-gray meaning “no flow”. Reach for it when something needs to know which way a surface runs: water and lava scrolling, brushed-metal anisotropy, wood grain, fur and hair. The encoding matches what Warp and Vector Morph expect, so it feeds them directly.

Inputs

  • Input (any texture, required): the height or mask the direction is derived from.
  • Mask (grayscale, optional): where dark, the node’s input passes through unchanged: the height itself, not neutral flow.

Outputs

  • Output (color): a direction field in the red and green channels; blue is always 0.
ParameterTypeDefaultRange / OptionsNotes
ModeChoiceDownhillDownhill, Along ContoursDownhill points the way water would run off the surface. Along Contours rotates the field a quarter turn so it follows contours instead of crossing them.
ScaleFloat4.01.0 to 64.0How far apart the samples that measure direction sit, in pixels. Raise it on smooth inputs; too small a spacing quantizes the field into a handful of angles and facets it.
CurlFloat0.00.0 to 1.0Mixes in a swirling component, so flow curls around features rather than piling up against them. At 0 the field is pure gradient.
IntensityFloat1.00.0 to 1.0Length of the output vectors. At 0 the map flattens to no flow.

Where the input is flat, the measured gradient falls below one 8-bit step, which is rounding noise rather than slope, so the vector fades to zero length instead of being normalized up into a full-strength random direction. Flat areas therefore read as mid-gray no-flow, and a Warp or Vector Morph driven by this node leaves them alone rather than shredding them into noise.

Type id: roughness_from_height

Derives a plausible roughness map from how busy the height is locally, not from how high it is. A flat plateau and a flat valley floor read equally smooth, which no amount of Levels on the height map can express. A fast, physically sensible starting point you then tune.

Inputs

  • Input (any texture, required): the height field to measure.
  • Mask (grayscale, optional): where dark, the node’s input passes through unchanged: the height itself, not a roughness value.

Outputs

  • Output (grayscale): a roughness map.
ParameterTypeDefaultRange / OptionsNotes
RadiusFloat0.020.001 to 0.25Detail scale, as a fraction of the shorter image edge. Small counts only fine grain; large also counts broad undulation as roughness.
SmoothFloat0.20.0 to 1.0The roughness value assigned to perfectly flat areas.
RoughFloat0.90.0 to 1.0The roughness value assigned to the busiest areas. Set it below Smooth to invert the mapping.
ContrastFloat1.00.1 to 4.0Response curve. Above 1, only the busiest areas reach the rough end. Below 1 it lifts faint detail toward the rough end without dragging flat areas with it: the dither floor every generator bakes into its output is subtracted before the curve, so a flat surface stays at Smooth at any Contrast.

The measurement weights occasional sharp steps well above uniform fine grain, matching how a chipped edge reads as rougher than an evenly grained surface.