Packages

Work with different noise functions using Elixir. Fork of isotope, maintained for Elixir 1.18+.

Current section

Files

Jump to
isotope_118 README.md
Raw

README.md

# Isotope (isotope_118)
Isotope is a library for generating noise in Elixir, backed by a Rust NIF.
Noise maps are returned as compact binaries of packed `f32` values (~4 bytes per value), making them suitable for generating large maps without excessive memory usage.
> **This is a fork.** `isotope_118` is a fork of [isotope](https://github.com/viniciusmuller/isotope)
> by Vinícius Müller / the Phiriq Project, published because upstream did not
> support Elixir 1.18+ and had seen no releases. Nearly all of the design and
> code is theirs. The fork adds Elixir 1.18+ support, a current `rustler`, and
> the changes listed in [CHANGELOG.md](CHANGELOG.md). Issues with *this* package
> belong here, not upstream.
The noise implementation is a vendored copy of
[bracket-noise](https://crates.io/crates/bracket-noise) (a Rust port of Auburn's
original [FastNoise](https://github.com/Auburn/FastNoise), not FastNoise Lite),
with several cellular-noise bugs fixed. See `native/noise/src/fastnoise.rs` and
`native/noise/THIRD_PARTY_LICENSES`.
## Installation
Add `isotope_118` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:isotope_118, "~> 0.5"}
]
end
```
And running `mix deps.get && mix deps.compile`.
A Rust toolchain is required to build the NIF: **rustc 1.91 or newer** (rustler
0.38's minimum). Distro packages often lag — `rustup` is the safe route.
## Usage
### Generating a Noise Map
```elixir
opts = %Isotope.Options{
seed: 42,
noise_type: :simplex_fractal,
frequency: 0.01,
fractal_options: %Isotope.Options.Fractal{octaves: 4}
}
{:ok, noise} = Isotope.Noise.new(opts)
# Returns an %Isotope.NoiseMap{} struct
nm = Isotope.Noise.noise_map(noise, {1000, 1000})
```
### Accessing Values
```elixir
# Single value at column x, row y
Isotope.NoiseMap.get(nm, 50, 50)
# Entire row as a list of floats
Isotope.NoiseMap.row(nm, 0)
# Dimensions
{width, height} = Isotope.NoiseMap.size(nm)
# Convert to nested list [[float()]]
Isotope.NoiseMap.to_list(nm)
```
### Using with Enum
`Isotope.NoiseMap` implements `Enumerable`, iterating over rows:
```elixir
# Average value per row
Enum.map(nm, fn row -> Enum.sum(row) / length(row) end)
# Visualize in the terminal
Isotope.Utils.show_noisemap(nm)
```
### Chunks (Infinite Worlds / Tiling)
Generate a noise map starting at an arbitrary coordinate:
```elixir
chunk = Isotope.Noise.chunk(noise, {512, 512}, 256, 256)
```
### Sampling Individual Points
```elixir
# 2D
value = Isotope.Noise.get_noise(noise, {1.5, 2.5})
# 3D
value = Isotope.Noise.get_noise(noise, {1.5, 2.5, 3.5})
```
### Noise Types
Isotope supports the following noise types via the `:noise_type` option:
| Type | Atom |
|------|------|
| Simplex | `:simplex` |
| Simplex Fractal | `:simplex_fractal` |
| Perlin | `:perlin` |
| Perlin Fractal | `:perlin_fractal` |
| Value | `:value` |
| Value Fractal | `:value_fractal` |
| Cubic | `:cubic` |
| Cubic Fractal | `:cubic_fractal` |
| Cellular (Voronoi) | `:cellular` |
| White Noise | `:white` |
### Options
See `Isotope.Options`, `Isotope.Options.Fractal`, and `Isotope.Options.Cellular` for all available configuration.
```elixir
%Isotope.Options{
seed: 1337, # Random seed
noise_type: :simplex, # Noise algorithm
frequency: 0.01, # Controls noise scale
interpolation: :quintic, # :linear | :hermite | :quintic
fractal_options: %Isotope.Options.Fractal{
fractal_type: :fbm, # :fbm | :billow | :rigid_multi
octaves: 3, # Number of fractal layers
lacunarity: 2.0, # Frequency multiplier per octave
gain: 0.5 # Amplitude multiplier per octave
},
cellular_options: %Isotope.Options.Cellular{
distance_function: :euclidean, # :euclidean | :manhattan | :natural
return_type: :cell_value, # :cell_value | :distance | :distance2 | ...
distance_indices: {0, 1},
jitter: 0.45
}
}
```
For more information, check the documentation
[here](https://hexdocs.pm/isotope_118).
## Examples
You can check and run the examples in the `examples` folder.
```bash
mix run examples/<example>.exs
```
## Images
![Output of the terrain.exs example script](images/terrain.png)
![Output of the visualization.exs example script](images/visualization.png)