Both halves of §27's phrase are here: inclusion is the hard test (outside
the volume the field contributes exactly (0, 0, 0)), filtering is the
weight (out = w · inner.sample(...) with w ∈ [0, 1]).
The weight is computed from the position only — never from velocity or
time — as smoothstep(t) where t is the normalised depth inside the edge
band, smoothstep(t) = t²(3 − 2t). Smoothstep rather than a linear ramp
because a linear weight has a discontinuous derivative at both ends of the
band, which is visible as a crease when a particle drifts through it. The
weight is monotone non-increasing as the sample point moves outward along
any ray from the centre, on both shapes; for the box, t is the minimum of
the three per-axis depths, so the weight is governed by whichever face is
nearest and the fade bands simply overlap in the corners.
Outside the volume the inner field is not sampled at all. That is the
performance point of wrapping turbulenceField, and it is observable:
an inner field that counted its calls would see fewer. Inner fields are
required to be pure (§33), so this is not a behavioural difference.
Wrapping composes — volumeField(volumeField(f, a), b) multiplies the two
weights — but each layer costs a virtual call.
§27's volume-based inclusion and filtering: restricts any field to a region, with an optional soft edge.
Both halves of §27's phrase are here: inclusion is the hard test (outside the volume the field contributes exactly
(0, 0, 0)), filtering is the weight (out = w · inner.sample(...)withw ∈ [0, 1]).The weight is computed from the position only — never from velocity or time — as
smoothstep(t)wheretis the normalised depth inside the edge band,smoothstep(t) = t²(3 − 2t). Smoothstep rather than a linear ramp because a linear weight has a discontinuous derivative at both ends of the band, which is visible as a crease when a particle drifts through it. The weight is monotone non-increasing as the sample point moves outward along any ray from the centre, on both shapes; for the box,tis the minimum of the three per-axis depths, so the weight is governed by whichever face is nearest and the fade bands simply overlap in the corners.Outside the volume the inner field is not sampled at all. That is the performance point of wrapping turbulenceField, and it is observable: an inner field that counted its calls would see fewer. Inner fields are required to be pure (§33), so this is not a behavioural difference.
Wrapping composes —
volumeField(volumeField(f, a), b)multiplies the two weights — but each layer costs a virtual call.