Skip to content

Give each fracture axis its own seed - #3

Draft
piexelated wants to merge 1 commit into
masterfrom
fix/fracture-mirror
Draft

piexelated wants to merge 1 commit into
masterfrom
fix/fracture-mirror

Conversation

@piexelated

@piexelated piexelated commented Nov 14, 2026 •

Copy link
Copy Markdown

Summary

CNG fractures warped the second axis by reading the same fracture noise at swapped coordinates, so every fractured style mirrored itself across x = z. CellGenerator's shuffle had the same swap. Each axis now gets its own reseeded fracture, read at unpermuted coordinates.

 2D
-  fz = z + fracture(z, x)
+  fz = z + fracture1(x, z)
 3D
-  fy = y + fracture(y, x)
-  fz = z + fracture(z, x, y)
+  fy = y + fracture1(x, y)
+  fz = z + fracture2(x, y, z)
  • CNG.fractureAxisSeed(seed, axis) derives the seed. Axis 0 keeps the fracture's own seed, so the x warp is unchanged. Axes 1 and 2 use a splitmix64 mix, because seed + k would collide with RNG.nextParallelRNG.
  • fracture.reseededForAxis(axis) returns a cached copy rebuilt from that seed. Custom generators can't be rebuilt from a seed, so they get a seed-derived offset instead.
  • A reseeded fracture is an ordinary node with its own seed, so the native and GPU kernels and the Rust crate are untouched, and zoom stays exact.

Evidence

Fractured noise before and after, master vs this branch

Same seeds and coordinates. Each badge is the share of pixels equal to their mirror across x = z. The grid's 65.5% on this branch is chance agreement, since most of its pixels are background.

  • Before: CNGFractureMirrorTest fails on master, 780 of 780 sample pairs mirrored.
    After: it passes.
  • NoiseProgramParityTest passes unchanged, and 79 of the 207 parity shapes stay native-backed, the same as master.
  • All 42 util.noise test classes pass on linux-x86_64, 164 tests.
  • GPU tests not run, this machine has no GPU.

Speedup per sampling path, master time ÷ branch time

NoiseProgramBenchmark, median of 8 alternating master/branch pairs. The noise floor is ±4%.

  • Deep fracture chains are 1.2 to 1.6× faster on every 3D path, because each level needs at most 4 reads instead of up to 9.
  • 2D and single-level fractures are flat.
  • NOWHERE 3D scalar is about 10% slower and 2D scalar on the double chains about 7% slower.

Merge Danger

Door: one-way

Fractured terrain changes for existing worlds, structure carve blobs and CellGenerator output included. There is no compatibility flag.

Blast Radius: worldgen

VolmitSoftware/Iris#1264 moves Iris to CNG.fractureAxisSeed and CNG.reseededForAxis. It does not compile against VolmLib master, so merge this PR first. The Mac pin in NoiseSeedCohesionTest is still stale there. A CNG subclass that changes sampling must override reseededForAxis, since its reseeded copy is a plain CNG.

- Warp the second and third axes with copies of the fracture reseeded by CNG.fractureAxisSeed, read at the same coordinates as the first axis, instead of reading the fracture at swapped coordinates
- Add CNG.reseededForAxis, which caches the copies and drops them when the fracture changes
- Shuffle the z axis of CellGenerator with reseeded copies of its noise
- Compile the per-axis fracture reads as ordinary terms on their own nodes, so fractured programs stay on the native and GPU kernels
- Rewrite the planar scalar chain for one term per axis and level, and drop the signed chain, which no program reaches anymore
- Add CNGFractureMirrorTest and update the reference formulas and instrumentation of the fracture tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant