Research: integration-native volumetric noise domain probe (cultmath-tapes)
A domain built so span integration holds by construction: sums of nonnegative compact ellipsoid kernels in a mass-conserving multiplicative cascade, per-kernel affine warp, all nonlinearity moved into placement. Measured on Yggdrasil against the shipped void and wells, with a physical reference (Beer-Lambert, single scattering with HG). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
082aec7962
commit
114bb4f380
1 changed files with 291 additions and 0 deletions
291
docs/research/integration-native-noise-domain.md
Normal file
291
docs/research/integration-native-noise-domain.md
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
# An integration-native volumetric noise domain: probe
|
||||
|
||||
Campaign `cultmath-tapes`, Imagination probe, 2026-10-03, under ruling
|
||||
`cultmath-tapes:ruling:integration-native-noise-domain`. This is research under the
|
||||
parked tape target. It has no spec, no shipped-field change and no committed code.
|
||||
|
||||
It follows `analytic-integration-feasibility.md`, which found that exact noise
|
||||
integrals are cheap but that the shipped densities are nonlinear in the noise. The
|
||||
question here is the reverse one. Suppose a domain is designed so that span
|
||||
integration holds by construction. Does it buy more visual detail per unit cost
|
||||
than the shipped fields?
|
||||
|
||||
On the operator's instruction (relayed by Self), the reference is physical, not
|
||||
Aetheria's tuned compositing:
|
||||
- transmittance is Beer–Lambert, `T = exp(-τ)`;
|
||||
- the images use single scattering with Henyey–Greenstein `g = 0.6` and albedo 1;
|
||||
- both fields are integrated the same way.
|
||||
|
||||
The shipped look is a comparison, not a target.
|
||||
|
||||
## Verdict
|
||||
|
||||
**On the void, yes, by a wide margin. On the wells, modestly.** At or below the
|
||||
shipped march's cost, the integration-native field carries much more resolvable
|
||||
detail, and it is exact. The catches:
|
||||
- The look changes character. The default cascade reads as fibres or brush strokes,
|
||||
not as soft cloud.
|
||||
- The cost is traversal, not integration.
|
||||
- The field cannot be ray-marched at all. Every consumer, shadow rays included,
|
||||
must use the exact path.
|
||||
|
||||
Headline numbers, 512 x 256, single-threaded C# on Yggdrasil:
|
||||
|
||||
| Void, transmittance image | Cost per pixel | vs shipped march | msf (grad²/var) | Power above 1/8 cycle/px | Pixels with \|∇T\| > 0.05 |
|
||||
|---|---|---|---|---|---|
|
||||
| Shipped field, converged reference (595 samples) | n/a | n/a | 0.0111 | 0.20% | 0.00% |
|
||||
| Shipped march (11.4 samples) | 28.9 µs (44 snoise3) | 1.00x | 0.0178 | 0.71% | 0.00% |
|
||||
| Integration-native, 2 levels, exact | 13.9 µs | **0.48x** | **0.0755** | **2.95%** | 41.9% |
|
||||
| Integration-native, 3 levels, exact | 35.7 µs | 1.24x | 0.125 | 9.15% | 54.7% |
|
||||
| Integration-native, 6 levels (LOD stops at 4 to 5), exact | 74.2 µs | 2.57x | 0.159 | 12.5% | 60.9% |
|
||||
|
||||
- **Mean density is matched.**
|
||||
- The integration-native field places mass from the shipped field's noise-averaged
|
||||
density.
|
||||
- Mean window optical depth is 1.62 to 1.74 against the shipped 1.81.
|
||||
- Mean T is 0.25 to 0.40 against 0.17. The difference comes from intermittency:
|
||||
the image std is 0.29 against 0.05, at a near-equal mean.
|
||||
- **msf is normalised by variance.** It measures spatial frequency, not contrast.
|
||||
- **Single-scattering images, void.** The images are 256 x 128 with a point light at
|
||||
the sun, and both are tonemapped with the same exposure. The shipped image's msf
|
||||
is 0.0023, with 0.22% of power above 1/8. The integration-native image's msf is
|
||||
0.101, with 16.9% of power above 1/8.
|
||||
- **Wells.**
|
||||
- Transmittance is a near-opaque silhouette for both fields: equal msf (0.011),
|
||||
so it carries no signal.
|
||||
- Single scattering at 6 levels (1.20x the march cost):
|
||||
- msf is 0.073 against 0.069;
|
||||
- power above 1/8 is 10.1% against 7.0%;
|
||||
- the edge fraction is 16.7% against 9.5%.
|
||||
- At 4 levels the cost is 0.77x the march.
|
||||
|
||||
**Exactness.** Against a converged march of the same field at 0.02 world:
|
||||
- The relative τ error is a median 3e-5 and a maximum of 1.0e-4 on the void, and a
|
||||
median 1e-5 and a maximum of 1.0e-4 on the wells.
|
||||
- The binned gather against brute force over all roots differs by at most 1.3e-15.
|
||||
- The shipped march against its own converged reference: |ΔT| is a median 0.0055
|
||||
(p90 0.013) on the void and a median 0.0006 (max 0.83 on grazing rays) on the
|
||||
wells.
|
||||
|
||||
**The detail is only reachable by integration.**
|
||||
- Marching the same integration-native field at the shipped step gives a void |ΔT|
|
||||
median of 0.14, a p90 of 0.48 and a maximum of 0.83.
|
||||
- A field this detailed is beyond the march at its step. That is the operator's
|
||||
premise, measured: the shipped fields' softness fits the regime that renders them.
|
||||
|
||||
## The primitive set
|
||||
|
||||
The primitive set has one design rule: nonlinearity lives in kernel placement, and
|
||||
linearity lives in the integration. The density is a sum of nonnegative,
|
||||
compact-support kernels. Everything nonlinear is evaluated once per kernel, at its
|
||||
centre, and never per sample. That covers envelopes, clamps, `pow` profiles, the
|
||||
flow warp and placement.
|
||||
|
||||
### Bases (closed-form line integral over a segment)
|
||||
|
||||
| Primitive | Why it integrates | Cost per span (measured unless marked) |
|
||||
|---|---|---|
|
||||
| Compact polynomial ellipsoid kernel, `(1 − u)^k` with `u = \|A⁻¹(x − μ)\|²` | On a line, u is quadratic in t, so the kernel is a polynomial of degree 2k between the two roots of `u = 1`, which are closed form. Same algebra as the simplex lattice integral in the first probe | k = 0: 5.5 to 7.4 ns; k = 1: 8 to 9.5 ns; k = 2: 11.7 ns. About 0.01 to 0.02 snoise3 (snoise3 is 610 to 650 ns in C#) |
|
||||
| Truncated Gaussian ellipsoid, `exp(−κu)` on `u ≤ 1` | `exp` of a quadratic is a Gaussian in t, giving an erf difference. Truncation only clips the limits | 32 to 36 ns with A&S 7.1.26 erf (error ≤ 1.5e-7), about 0.05 snoise3 |
|
||||
| k = 0 ellipsoid (constant density) | Chord length; this is EVER's primitive (Mai et al. 2024 [memory]) | 5.5 ns |
|
||||
| Gabor kernel (Gaussian × cosine) | Complex erf, any affine transform (Gabor Fields 2026, eq. 9 [fetched in the prior-art file]) | Not probed. Up to 16 Taylor terms [paper] |
|
||||
| Cosine sum (Balint 2019) | Integral is a sum of sines | Not probed. Two noise-sized evaluations per segment [paper]. Signed, so it needs an offset; low contrast |
|
||||
| Simplex lattice (CultMath `snoise`) | First probe: degree 9 per lattice point | 0.16 snoise3 per point, 3.44 points per noise unit. Signed: only usable where density is affine in it |
|
||||
|
||||
### Warps
|
||||
|
||||
| Warp | Why it stays exact | Cost |
|
||||
|---|---|---|
|
||||
| Per-kernel affine warp: centre moved by `f(μ)·s`, shape by `(I + J·s)` | An affine image of an ellipsoid is an ellipsoid, so the ray stays straight and the kernel stays closed form. The warp *defines* the field, so there is no approximation error. It is evaluated once per root per frame (7 flow evaluations with the Jacobian) | Frame build 39 ms (void, 2540 roots) and 57 ms (wells, 16947 roots), or 19 and 27 ns per 1080p pixel amortised |
|
||||
| Children inherit the parent's affine frame | The cascade has descendants that are exact affine images, so the warp is evaluated only at the roots | One 3x3 product per child, from a table |
|
||||
| Not allowed | A per-point warp `x + w(x)` inside a span: the warped ray curves, which was the first probe's problem | n/a |
|
||||
|
||||
### Transfer and placement
|
||||
|
||||
| Rule | Status |
|
||||
|---|---|
|
||||
| Any function of the kernel centre: the shipped clamp, `pow`, the smoothstep fade, the noise-averaged density `E_n[ρ(x, n)]` from 16 empirical noise quantiles, through a 1D LUT over d (void) or s (wells) | Exact by construction, at one lookup per kernel |
|
||||
| Affine transfer of the sum (`a + b Σ K_i`) | Exact |
|
||||
| Any 1D function of an *affine* coordinate, `∫ f(a + bt) dt = ΔF / b` (pre-integration, Engel 2001) | Exact [derivation, not probed]: height fog `exp(−y/h)` and ramps in y |
|
||||
| Polynomial or exp of a *quadric* coordinate; an indicator or clamp of a quadric (chord through roots) | Exact [derivation, not probed]: spherical shells and paraboloid bowls as envelopes |
|
||||
| Product of the sum with a polynomial envelope in t | Exact, polynomial times polynomial [derivation, not probed] |
|
||||
| Forbidden inside a span: `f(Σ K_i)` for nonlinear f, `max`/`min` of fields, a clamp of a signed sum, or noise displacing an envelope's argument | These are exactly what broke the first probe |
|
||||
|
||||
### Composition: the mass-conserving multiplicative cascade
|
||||
|
||||
- **Roots** sit on a jittered grid: spacing H0 = 30 world on the void and 40 on the
|
||||
wells, one root per cell.
|
||||
- Mass is `P(μ)·H0³`, so the mean density equals the shipped noise-averaged
|
||||
density.
|
||||
- The ellipsoid is elongated along the flow direction projected on the shell or
|
||||
fog layer (aspect 1.3 to 2.4), with ±0.6 rad of jitter, and flattened along the
|
||||
normal (×0.5 void, ×0.4 wells).
|
||||
- There are two copies per root, at the shipped two-phase shifts with weights w0
|
||||
and 1 − w0. Time animation is therefore the shipped crossfade, exact under
|
||||
summation.
|
||||
- **Children.** Each node keeps 25% of its mass and gives 75% to Nc = 5 children.
|
||||
- Child weights are `u²·P(child)/P(parent)`, normalised. The `u²` makes the cascade
|
||||
intermittent; the P ratio sharpens it toward the envelope.
|
||||
- A child is scale 0.4, with aspect up to 1.6 and ±0.6 rad of rotation.
|
||||
- Children sit along the parent's major axis: offset 0.6 along it, 0.21 across.
|
||||
- All of this comes from a 256-entry table indexed by hash. A descendant bound of
|
||||
1.77 times the ellipsoid holds the subtree, so the parent is a BVH node.
|
||||
- **LOD.** A node is a leaf when its children would be smaller than 0.5 × the pixel
|
||||
footprint at that depth. It then keeps its full mass. Because the cascade conserves
|
||||
mass, truncation is a mean-preserving prefilter: the expectation step of the first
|
||||
probe, exact here instead of approximate.
|
||||
- **Gather.**
|
||||
- Roots are binned by their subtree AABB into a hash grid of H0 cells.
|
||||
- The ray walks the grid with Amanatides–Woo DDA and mailboxing, clipped to the
|
||||
shipped active windows, so both fields integrate the same span.
|
||||
- It exits early once Στ ≥ 7, which is valid because every term is nonnegative.
|
||||
|
||||
## "Juice" under these constraints
|
||||
|
||||
| Effect | Mechanism here | Measured or prior art |
|
||||
|---|---|---|
|
||||
| Filaments, wisps | Anisotropic children chained along the parent's major axis, which follows the flow | Visible in `void-T-IN-L6.png` as streaks along the flow. Gabor Fields uses anisotropic Gabor kernels for orientation-selective detail [fetched] |
|
||||
| Sharp edges | Low-order kernels: k = 1 is the default, k = 0 gives hard ellipsoids | k = 0 (`L6-hard`) changes msf by −9% on the void. Edges come from kernel boundaries, not clamps |
|
||||
| Voids | Regions with no kernel mass are exactly zero and are skipped by the gather at no cost | Structural |
|
||||
| Turbulent intermittency | Random multiplicative cascade, the p-model of turbulent dissipation (Meneveau & Sreenivasan 1987 [memory]); clustered kernels, as in a Neyman–Scott process [memory] | Image std 0.29 against 0.05 at near-equal mean OD |
|
||||
| Flow and animation | Per-kernel warp at the shipped flow and phases. Alternatives are Lagrangian advection of kernel centres with lifetimes (advected textures, Neyret 2003 [memory]) and Gabor phase for oscillatory detail (flow noise, Perlin & Neyret 2001 [memory]) | Only the two-phase crossfade was measured |
|
||||
| Fine detail riding on structure | Children exist only inside parents, so detail appears only where matter is. This is Schneider's erosion idea (2015 [fetched]) without the per-sample clamp | Structural |
|
||||
|
||||
Wavelet turbulence (Kim et al. 2008 [memory]) and curl noise (Bridson 2007 [memory])
|
||||
were not used. A per-point warp is ruled out above. Curl noise could orient kernels,
|
||||
evaluated per kernel, at no cost to exactness.
|
||||
|
||||
## Measurements
|
||||
|
||||
**Setup.**
|
||||
- Probe source: scratch clone `probe-clone@5ec9f529`,
|
||||
`packages/cultmath/probe/DomainProbe/Program.cs`, never merged.
|
||||
- Run on Yggdrasil through the verify stopgap: dotnet 10 container, 4 CPUs, tiered
|
||||
JIT off.
|
||||
- Full log: Self's scratchpad, `dom-full1.log`.
|
||||
- The scenes are those of the first probe, with fixed cameras:
|
||||
- Void: the shipped orbiting camera at time 20, at the 1920-wide f = 935 field of
|
||||
view, rendered at 512 x 256.
|
||||
- Wells: warp D = 60, camera at xz (1200, 0) looking at the central well, slopes
|
||||
x ±1 and y from −0.85 to 0.15.
|
||||
- The window is the shipped field's active intervals. Every method integrates the
|
||||
same window.
|
||||
|
||||
**Cost.**
|
||||
- Single-threaded C#, best of three passes over the same 2048 random pixels.
|
||||
- The host is shared, and absolute timings moved by up to 2x between the smoke run
|
||||
and the full run; Flow went from 125 to 660 ns. Ratios within one run are the
|
||||
reliable numbers.
|
||||
- Flow is 47% of a shipped sample in this run, so a flow-cached march would cost
|
||||
about 15 µs on the void and 31 µs on the wells.
|
||||
|
||||
| Config (void) | Cost vs march | Roots visited / nodes tested / kernels integrated per pixel | Kernels per level |
|
||||
|---|---|---|---|
|
||||
| L1 | 0.12x | 43 / 8 / 8 | 8 |
|
||||
| L2 | 0.48x | 59 / 25 / 20 | 8, 12 |
|
||||
| L3 | 1.24x | 74 / 42 / 28 | 8, 12, 8 |
|
||||
| L4 | 1.81x | 82 / 60 / 35 | 8, 12, 8, 7 |
|
||||
| L6 (default) | 2.57x | 93 / 86 / 36 | 8, 12, 8, 7, 1, 0 |
|
||||
| L6, no child placement | 1.79x | 93 / 91 / 39 | same metrics as L6 |
|
||||
| L6, no LOD | 2.95x | 93 / 103 / 49 | 8, 12, 8, 7, 7, 7 |
|
||||
|
||||
| Config (wells) | Cost vs march | Kernels integrated per pixel |
|
||||
|---|---|---|
|
||||
| L1 | 0.04x | 5 |
|
||||
| L2 | 0.23x | 11 |
|
||||
| L3 | 0.49x | 16 |
|
||||
| L4 | 0.77x | 20 |
|
||||
| L6 | 1.20x | 25 |
|
||||
| L6, no child placement | 0.62x | 27 |
|
||||
|
||||
**Where the time goes.**
|
||||
- The integrals are about 36 kernels × 10 ns, or 0.4 µs of a 74 µs pixel.
|
||||
- The rest is traversal:
|
||||
- roots visited but missed: 93 visited for 8 hits, because AABBs of elongated
|
||||
rotated ellipsoids are loose;
|
||||
- child generation;
|
||||
- placement lookups. The wells' placement costs a 5-bowl `Sdf`, and dropping
|
||||
child placement halves the wells cost with identical metrics.
|
||||
|
||||
**Aliasing.** One sample per pixel against four on the default void field: |ΔT| has
|
||||
an RMS of 0.015 (p90 0.022). At 4 spp the msf is 0.146 against 0.159. So about 92%
|
||||
of the measured detail is resolved structure, not sparkle. Exact along the ray is
|
||||
not the same thing as antialiased across the pixel; the LOD rule is the prefilter.
|
||||
|
||||
**Variants, void L6 (msf / power above 1/8).**
|
||||
- k = 1 default: 0.159 / 12.5%.
|
||||
- Hard k = 0: 0.145 / 11.0%.
|
||||
- Gaussian (erf): 0.174 / 14.2%, at 0.89x the polynomial cost here. The erf kernel is
|
||||
3x the polynomial kernel in isolation, but the kernel is not where the time goes.
|
||||
|
||||
## Images
|
||||
|
||||
All images are in Self's session scratchpad,
|
||||
`C:\Users\Meta\AppData\Local\Temp\claude\F--Projects-CultLib\b7e842a1-2045-474e-a51b-240d832b770b\scratchpad\integration-domain-images\`:
|
||||
|
||||
- **Transmittance, 512 x 256.** Shown as `sqrt(1 − T)`, white for opaque.
|
||||
- `void-T-shipped-ref.png`, `void-T-shipped-march.png`.
|
||||
- `void-T-IN-L1.png`, `void-T-IN-L3.png`, `void-T-IN-L6.png`,
|
||||
`void-T-IN-L6-hard.png`, `void-T-IN-L6-gauss.png`.
|
||||
- The wells equivalents, which are silhouettes and uninformative.
|
||||
- **Single scattering, 256 x 128.**
|
||||
- Method: HG g = 0.6 and albedo 1. The point light is at the void's sun with 1/r²
|
||||
falloff; the wells use a directional sun with a sky background.
|
||||
- Each view sample takes a shadow ray: a 2-world march for the shipped field, an
|
||||
exact traversal for the integration-native field.
|
||||
- Tonemap: `1 − exp(−1.5 L / p99(shipped))`, then gamma 2.2, the same exposure for
|
||||
both fields.
|
||||
- `void-SS-shipped.png`, `void-SS-IN-L6.png`, `wells-SS-shipped.png`,
|
||||
`wells-SS-IN-L6.png`.
|
||||
|
||||
What they show:
|
||||
- The shipped void is a soft, low-contrast haze.
|
||||
- The integration-native void is dense flow-aligned streaks with deep gaps, like
|
||||
hair or brush strokes.
|
||||
- The shipped wells are smooth rolling dunes. The integration-native wells are
|
||||
layered pancakes with streaked detail.
|
||||
|
||||
## The catches
|
||||
|
||||
1. **The character is a design parameter, and this probe picked one.**
|
||||
- High anisotropy, axis-chained children and an intermittent `u²` split give
|
||||
fibres.
|
||||
- A cloudier look would need rounder children, wider offsets and less
|
||||
intermittency. That trades away some measured detail and was not swept.
|
||||
- The detail metrics measure spatial frequency, not taste. The operator has to
|
||||
look at the images.
|
||||
2. **The cost is a BVH, not arithmetic.**
|
||||
- Integration is nearly free. Traversal, child generation and placement dominate.
|
||||
- Tighter root bounds (OBB tests before AABB bins), cheaper placement and fewer
|
||||
children are obvious levers, but none was measured.
|
||||
- On a GPU, variable-length kernel lists per ray diverge. 3DGRT (Moënne-Loccoz et
|
||||
al. 2024 [memory]) puts the same problem on hardware ray tracing.
|
||||
- CPU C# ratios do not transfer to the GPU, where snoise is relatively cheaper.
|
||||
3. **It is all or nothing.**
|
||||
- This field cannot be marched. At the shipped step, |ΔT| is a median 0.14.
|
||||
- Shadow rays, light probes and any sampler consumer need the exact traversal too.
|
||||
The single-scattering pass here cost an exact shadow traversal per view sample:
|
||||
257 s for both void SS images together, against 54 s for the whole 512 x 256
|
||||
shipped transmittance set.
|
||||
- Lighting has no closed form. The in-scatter integral is still quadrature. What
|
||||
the domain makes exact is every optical depth inside it. A per-kernel lighting
|
||||
cache would amortise shadows, but that is a different shading model (splat-like),
|
||||
and so a product fork.
|
||||
4. **Exact along the ray, not across the pixel.** The LOD truncation is the
|
||||
prefilter. 8% of the measured detail at 1 spp is aliasing.
|
||||
5. **The wells gain little** because the shipped wells fog is near-opaque. Its look
|
||||
is the surface silhouette, and that is set at root scale. The domain pays most
|
||||
where the medium is semi-transparent, as in the void.
|
||||
6. **Timing noise.** Absolute costs vary up to 2x between runs on the shared host.
|
||||
The cost ratios above are within one run.
|
||||
|
||||
## What would change the verdict
|
||||
|
||||
- A sweep toward a cloud-like character: round children, Nc = 8, wider offsets,
|
||||
Gaussian kernels. It should be judged on the single-scattering images against the
|
||||
same cost.
|
||||
- Tight root culling: an exact ellipsoid-versus-bin test, or roots stored by
|
||||
oriented bound. If roots visited fall from 93 to near the 8 hits, the void L3 cost
|
||||
would fall well under the march.
|
||||
- A GPU port of one level-limited configuration, to replace the C# ratios with
|
||||
shader timings.
|
||||
Loading…
Reference in a new issue