Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Comparing to Other Libraries

Disclaimer: I don't maintain these other projects. There may have been updates, etc, or there may be other ways to improve their performance from a user's perspective. If you see a way to represent them more fairly, feel free to submit a PR!

Quick Facts

FeatureNoizNoiselibnoisefastnoise_lite
precisionf32f64f64f32
dimensions2d, 3d, 4d2d, 3d, 4d1d, 2d, 3d, 4d2d, 3d,
customizabilitytotalsomesomelimited choices
cross-language
no-std
overall performanceGreatPoorGreatGood
overall noise qualityGooduntestedOk for small domainsOk

(If you want great noise quality, use an art application like blender.)

Benchmarks

All benchmarks are on a standard M2 Max with the same build configuration recommended above.

Each dimension's benchmarks contain roughly the same number of samples.

All benchmarks are as even as possible. For example, they all do smoothstep interpolation, default seeding, etc.

Only a few combinations of noiz's types are benched. If you are creating your own noise functions, it will always be best to create your own benchmarks for your own specific uses.

2D

Time (milliseconds) per 1024 ^ 2 = 1048576 samples. Lower is better.

Noise Typenoiznoiselibnoisefastnoise_lite
value1.7365 ✅3.11.8831 ✅14.8
value fbm 2 octave7.18.65.8 ✅31.4
value fbm 8 octave29.533.422.0 ✅112.0
perlin3.4 ✅8.83.0 ✅8.1
perlin fbm 2 octave8.6 ✅18.48.1 ✅17.2
perlin fbm 8 octave36.771.831.1 ✅58.0
simplex7.0 ✅8.68.110.6
simplex fbm 2 octave14.7 ✅22.317.721.6
simplex fbm 8 octave57.8 ✅108.589.2116.0
worley5.7 ✅24.511.817.8
worley approximate2.8 ✅---------

Note that "worley approximate" is a faster version of "worley" with some compromises.

3D

Time (milliseconds) per 101 ^ 3 = 1030301 samples. Lower is better.

Noise Typenoiznoiz Vec3Anoiselibnoisefastnoise_lite
value3.07.811.42.7 ✅39.6
value fbm 2 octave13.216.022.58.2 ✅85.7
value fbm 8 octave56.860.789.333.5 ✅336.6
perlin7.111.476.96.4 ✅13.8
perlin fbm 2 octave17.423.028.515.8 ✅29.7
perlin fbm 8 octave76.486.4368.969.7 ✅132.0
simplex12.9 ✅17.614.216.320.1
simplex fbm 2 octave27.3 ✅33.551.825.9 ✅43.0
simplex fbm 8 octave108.7 ✅129.8207.8181.7175.1
worley54.857.478.952.942.3 ✅
worley approximate6.2 ✅14.9---------

Vec3A is an aligned 3d type from bevy_math (glam). It enables SIMD instructions, but uses more memory to do so. As you can see, it's not worth it here.

4D

Time (milliseconds) per 32 ^ 4 = 1048576 samples. Lower is better.

Noise Typenoiznoiselibnoisefastnoise_lite
value13.821.23.9 ✅---
value fbm 2 octave27.746.014.3 ✅---
value fbm 8 octave109.0167.357.3 ✅---
perlin17.5 ✅177.617.6 ✅---
perlin fbm 2 octave38.3 ✅53.538.4 ✅---
perlin fbm 8 octave146.1 ✅824.2203.1---
simplex18.8 ✅35.529.5---
simplex fbm 2 octave36.6 ✅108.841.0---
simplex fbm 8 octave139.3 ✅421.0234.4---
worley186.8156.3 ✅205.8---
worley approximate26.3 ✅---------

Summary

For value noise, libnoise is the clear winner for performance. Both fastnoise_lite and noise are far behind. noiz is close, but not quite as fast. This is because libnoise uses a permutation table for it's rng where noiz uses a custom hash function. This mean two things: First, libnoise will invalidate a cache line, which is not reflected in these benches since nothing was competing for the cache. Second, libnoise will produce repeating noise from far away.

problem

See the tiling? This is at a frequency of 200. By contrast, here's noiz at a frequency of 1024:

good

No tiling. Yay! Note that some artifacting (not quite tiling) does happen at excessively large scales. But that's not a big deal in practice. (Ever wonder why the far lands exist in minecraft?)

For perlin noise, noiz and libnoise roughly tie for 2d; noiz is faster for 4d but libnoise just beats it for 3d. This is likely also due to the difference in rng methods, and the same quality issues and benchmark blind spots apply here too.

For simplex noise, noiz is the clear winner. Simplex is about half as fast as perlin for 2d, but it gets better for higher dimensions, beating perlin in 4d.

For Worley noise, the results vary greatly depending on use-case. See for yourself.

What to Choose

Use fastnoise_lite if you need consistncy across languages. Use libnoise if you don't need a ton of configuration, are using relatively small domains, and are primarily doing value and perlin noise. If you absolutely need f64 support, use libnoise, but again, the permutation table rng makes the large domain kinda a moot point. Same goes for noise. If you are integrating with bevy, need lots of customization, need general, high performance, or need serialization and reflection, use noiz. I am not aware of a reason to use noise (though there may well be one I'm missing).