Documentation / Node reference / mat nodes

mat/MeshSDF

Tunes how SDF objects are raymarched.

Sdf

Assign it to SDF objects with a geo/Material node. SDF objects already render without it, on these same defaults; this node is what makes the march tunable and adds the debug views. Every param is a uniform, so dragging one never recompiles the shader. Raise `maxStepsCount` when a shape shows holes or soft edges where the rays run out of steps, and lower it when a scene gets slow: the step-count debug view shows where the budget actually goes, silhouette rays being the expensive ones. Lower `surfaceDistance` for a crisper surface at the cost of more steps. `isoValue` moves which surface is drawn, so one tree can be looked at at several levels without touching it. It also carries the self-lighting the object gets from its own field: `shadowSoftness` for soft shadows where one part of the shape shadows another, on by default and scaling the width each light asks for with its own `softness`, and `aoStrength` for darkened creases, off by default. Both are per-object: neither sees any other object in the scene. `gridFiltering` is the one param that only some trees read: a field built from a volume (geo/SDFCreate) is a grid of voxels, and TRICUBIC reads between them with a continuous gradient, which is what removes the per-voxel faceting an imported model shows. A 2D field is not marched at all, it is painted as a distance-field visualization, so the only params it reads are `bandSpacing` and `isoValue`. `color`, `roughness`, `metallic` and `emissive` here are the DEFAULT surface, and an object that carries a shading record of its own overrides them: what a geo/MaterialAttributes wrote wins, per region of the field (see geo/SDFBoolean). Everything else on this node stays the object's, record or not. Drop a geo/Environment into the scene and SDF objects light from it like every other surface, with no wiring and without this node: the map is the scene's, so there is nothing here to point at it.

**Glass.** `transmission` above 0 lets light through the surface, with `ior`, `attenuationColor` and `attenuationDistance` describing the medium. At each pixel the light splits between a reflection and a refraction by the Fresnel term, so glass reflects mostly at grazing angles and shows what is behind it head on. The refracted ray crosses the object's own field to its far side and leaves toward the scene environment, so what shows through is the environment, not the rest of the scene; with no geo/Environment there is nothing to see through it. Turning `transmission` up from 0 regenerates the shader once, and so does turning it back to 0: an opaque object carries none of the transmission code. Every other drag of the four is an upload. An object carrying a shading record (geo/MaterialAttributes) takes its transmission from the record instead, per region of the field, the way its roughness does. An OPAQUE part inside a clear one shows through it, the skull inside a resin head: the refracted ray stops on it, shades it with its own colour and roughness under the scene lights and the environment, and dims it by `attenuationColor` over the stretch of medium in front of it (see geo/SDFBoolean for how the two regions are authored). That part is lit as if the medium were not around it: it casts and receives no shadow there, and the light reaching it is not tinted on its way in. A ray that cannot leave the medium (total internal reflection) turns around inside and carries on, up to `transmissionDepth` times, and `dispersion` splits the colours where it finally leaves (crossing 0 regenerates the shader once, like `transmission`). A ray that runs out of `maxStepsCount` steps inside the medium stops where it is and shows the environment straight ahead along its direction, the same as when `transmissionDepth` is spent: raise `maxStepsCount` if a long piece of glass looks clear where it should bend.

Parameters

Name Type What it does
maxStepsCount UInt32 How many sphere-trace steps a ray may take before giving up. Too few shows as holes and soft edges near silhouettes.
maxDistance Float How far along a ray the march goes before giving up. The object's bounds usually stop it first.
surfaceDistance Float How close to the surface counts as a hit. Smaller is crisper and costs more steps.
normalsBias Float Offset of the central-difference samples the normal is built from, in OBJECT units. 0 is AUTO, the default: an object whose tree holds a grid field (geo/SDFCreate on a volume) uses its largest voxel, since a smaller offset reads the per-voxel ripple as faceting that swims with the camera, and a tree of analytic primitives uses 0.01. Set it above 0 to override: larger smooths the shading and hides small details.
color Color Surface colour.
roughness Float Surface roughness. It also picks how blurred the scene environment's reflection is, when the scene carries a geo/Environment: 0 is a mirror, 1 spreads it over the whole surface.
metallic Float How metallic the surface is. A metal takes its colour from what it reflects, so on a metal SDF object the scene environment is most of what there is to see.
emissive Color A colour the surface gives off by itself, added after the lighting. It brightens this surface only and casts no light on anything else, so it is for something that should read as lit from within. Black, the default, adds nothing. An object carrying an EMISSION attribute overrides it, per region of the field.
debugView UInt8 NONE · STEP_COUNT · NORMAL · BOUNDS · AMBIENT_OCCLUSION Replaces the shading: STEP_COUNT is a cost heatmap (cool to hot, including the rays that never hit), NORMAL shows the surface normal, BOUNDS draws the edges of the box the march is clamped to, AMBIENT_OCCLUSION shows the `aoStrength` factor as grey (white is open, black is fully occluded, and it is all white while `aoStrength` is 0).
bandSpacing Float 2D fields only: the distance between two bands of the field visualization, in world units. It is a scene-scale setting rather than something read off the object's bounds, so translating one operand of a boolean never changes the frequency of the bands. It also sets how fast the colour darkens toward the surface.
isoValue Float Draw the surface where the field equals this value instead of the zero set: positive inflates the shape, negative erodes it. The proxy box grows with it, so an inflated surface is not clipped. It is a uniform, so sweeping it never recompiles the shader. It changes what is DRAWN, not the field itself; geo/SDFTriangulate has the same param for the meshed form.
shadowSoftness Float Soft shadows the object casts on ITSELF, marched through its own field, for every light. How WIDE each penumbra is belongs to the light, which carries its own `softness`, and this scales them all for this object: 1 leaves every light as authored, 2 doubles the spread, 0.5 halves it. A blocker far from the surface it shadows always spreads wider than one close to it, whatever this is set to. While it is above 0 the field is the object's ONLY shadow: the shadow atlas is not read for this surface, so nothing can stack into a double shadow, and equally an SDF plate does not receive the shadow of a mesh standing on it. Set it to 0 to go back to the atlas instead, which is the only way to receive shadows from other objects until the scene trace lands. Setting a LIGHT's softness to 0 does something else: that light keeps its shadow here, with a hard edge.
shadowStepsCount UInt32 The shadow march's step budget. It is a safety cap, not a reach: the march always crosses the whole ray whatever this is set to, and spending more of it only buys a finer march. Lower it first when self-shadowing costs too much, since there is one shadow ray per light per pixel.
aoStrength Float Darkens creases of the object using its own field, sampled along the normal (ambient occlusion). 0 turns it off, 1 is the full effect. It scales the ambient and hemisphere lights only, which is where ambient occlusion belongs, so a scene with neither shows no change.
aoRadius Float How far from the surface the ambient-occlusion samples reach, in OBJECT units. Roughly the size of the crease it responds to: small values catch fine detail, large ones darken whole concave regions.
gridFiltering UInt8 TRILINEAR · TRICUBIC How a grid field in the tree is read between its voxels. A grid field is what geo/SDFCreate makes from a volume, so a tree of analytic primitives never looks at this. TRILINEAR, the default, is 8 samples per read and has a gradient that jumps at every voxel face: the normal is that gradient, so an imported model shows one facet per voxel, and no `normalsBias` removes it, it only blurs it. TRICUBIC is 64 samples per read and has a continuous gradient, so the faceting goes rather than gets filtered. Switch to it when a model looks blocky under the light and leave it on TRILINEAR while framing a scene, since the cost is per march STEP.
transmission Float How much of the light the surface does not reflect goes THROUGH it. 0, the default, is opaque; 1 is clear glass. Crossing 0 in either direction regenerates the shader once, since an opaque object carries none of the transmission code, and any drag above 0 is an upload. An object carrying a TRANSMISSION attribute overrides it, per region of the field. A metal transmits nothing whatever this says.
ior Float Index of refraction of the medium: how much a ray bends entering and leaving it, and how strongly the surface reflects head on. 1.5 is glass and most resins, 1.33 water, 2.4 diamond. It is relative to the air around the object, so below 1 means a medium LESS dense than its surroundings, and the ray spreads out through it instead of converging: that is how to fake an air bubble in water (0.75) or in resin (about 0.67), since a medium inside another is not modelled. Below 1, a ray meeting the surface at a grazing angle cannot get in and is all reflected, so the rim shows only the reflection. Lowest value 0.25. Only read while `transmission` is above 0.
attenuationColor Color The colour white light turns after travelling `attenuationDistance` through the medium. The tint deepens with the length of the path, so a thick part of the object reads darker than a thin one. White absorbs nothing.
attenuationDistance Float How far, in world units, light travels through the medium before it has turned `attenuationColor`. Smaller is a denser tint. 0, the default, is infinite: nothing is absorbed.
transmissionDepth UInt32 How many times a ray inside the medium may meet its surface. Where it cannot leave (total internal reflection, the sparkle of a gem, the glow along the edge of a glass slab) it turns around and goes on inside, spending one. When they run out it shows the environment along the way it last turned. 1 never turns around at all. More costs more only on the pixels that need it, and a ray whose light is already absorbed stops early whatever this says. It is an upload, never a recompile.
dispersion Float Splits white light into colours where it leaves the medium, the fire of a diamond or a prism's fringes. The glTF value: 20 divided by the Abbe number of the material, so window glass is about 0.3, flint glass about 0.6, diamond about 0.4 (its high `ior` does most of the work), and higher values exaggerate it. 0, the default, is off. Only the last exit splits, into three looks at the environment, so the cost is two extra lookups per pixel, not three paths. Crossing 0 in either direction regenerates the shader once, like `transmission`; any drag above 0 is an upload. It is this node's alone: a shading record carries no dispersion.

See also

This page is generated from the engine, so it describes the release you can download. The same text is in the editor's Help panel next to the node itself.