orx-noise
A collection of noise generator functions. Source and extra documentation can be found in the orx-noise sourcetree.
Prerequisites
Assuming you are working on an openrndr-template
based project, all you have to do is enable orx-noise
in the orxFeatures
set in build.gradle.kts
and reimport the gradle project.
Uniformly distributed random values
The library provides extension methods for Double
, Vector2
, Vector3
, Vector4
to create random vectors easily. To create scalars and vectors with uniformly distributed noise you use the uniform
extension function.
val d1 = Double.uniform(0.0, 640.0)
val v2 = Vector2.uniform(0.0, 640.0)
val v3 = Vector3.uniform(0.0, 640.0)
val v4 = Vector4.uniform(0.0, 640.0)
To create multiple samples of noise one uses the uniforms
function.
val v2 = Vector2.uniforms(100, Vector2(0.0, 0.0), Vector2(640.0, 640.0))
val v3 = Vector3.uniforms(100, Vector3(0.0, 0.0, 0.0), Vector3(640.0, 640.0, 640.0))
The Random
class can also be used to generate Double numbers and vector, but also booleans and integers.
// Boolean
val b = Random.bool(probability = 0.2)
// Int
val i1 = Random.int(0, 640)
val i2 = Random.int0(640)
// Double
val d2 = Random.double(0.0, 640.0)
val d3 = Random.double0(640.0)
// Vectors
val v2 = Random.vector2(0.0, 640.0)
val v3 = Random.vector3(0.0, 640.0)
val v4 = Random.vector4(0.0, 640.0)
Perlin, Value and Simplex noise
Random.perlin()
and Random.value()
accept 2D and 3D arguments. Random.simplex()
up to 4D. They all return a Double
. Some examples:
// Test vectors to use
val v2 = Vector2(0.1, 0.2)
val v4 = Vector4(0.1, 0.2, 0.3, 0.4)
// Now generate random values
val d1 = Random.perlin(0.1, 0.2)
val d2 = Random.perlin(v2)
val d3 = Random.value(0.1, 0.2, 0.3)
val d4 = Random.simplex(v4)
Uniform ring noise
val v2 = Vector2.uniformRing(0.0, 300.0)
val v3 = Vector3.uniformRing(0.0, 300.0)
val v4 = Vector4.uniformRing(0.0, 300.0)
fun main() = application {
program {
extend {
drawer.fill = ColorRGBa.PINK
drawer.stroke = null
drawer.translate(width / 2.0, height / 2.00)
for (i in 0 until 1000) {
drawer.circle(Vector2.uniformRing(150.0, 250.0), 10.0)
}
}
}
}
Perlin noise
fun main() = application {
program {
extend {
drawer.fill = ColorRGBa.PINK
drawer.stroke = null
val scale = 0.005
for (y in 16 until height step 32) {
for (x in 16 until width step 32) {
val radius = perlinLinear(100, x * scale, y * scale) * 16.0 + 16.0
drawer.circle(x * 1.0, y * 1.0, radius)
}
}
}
}
}
Value noise
fun main() = application {
program {
extend {
drawer.fill = ColorRGBa.PINK
drawer.stroke = null
val scale = 0.0150
for (y in 16 until height step 32) {
for (x in 16 until width step 32) {
val radius = valueLinear(100, x * scale, y * scale) * 16.0 + 16.0
drawer.circle(x * 1.0, y * 1.0, radius)
}
}
}
}
}
Simplex noise
fun main() = application {
program {
extend {
drawer.fill = ColorRGBa.PINK
drawer.stroke = null
val scale = 0.004
for (y in 16 until height step 32) {
for (x in 16 until width step 32) {
val radius = simplex(100, x * scale, y * scale) * 16.0 + 16.0
drawer.circle(x * 1.0, y * 1.0, radius)
}
}
}
}
}
Fractal/FBM noise
fun main() = application {
program {
extend {
drawer.fill = ColorRGBa.PINK
drawer.stroke = null
val s = 0.0080
val t = seconds
for (y in 4 until height step 8) {
for (x in 4 until width step 8) {
val radius = when {
t < 3.0 -> abs(fbm(100, x * s, y * s, t, ::perlinLinear)) * 16.0
t < 6.0 -> billow(100, x * s, y * s, t, ::perlinLinear) * 2.0
else -> rigid(100, x * s, y * s, t, ::perlinLinear) * 16.0
}
drawer.circle(x * 1.0, y * 1.0, radius)
}
}
}
}
}
Noise gradients
Noise functions have evaluable gradients, a direction to where the value of the function increases the fastest. The gradient1D
, gradient2D
, gradient3D
and gradient4D
functions can be used to estimate gradients for noise functions.
fun main() = application {
program {
extend {
drawer.fill = null
drawer.stroke = ColorRGBa.PINK
drawer.lineCap = LineCap.ROUND
drawer.strokeWeight = 3.0
val t = seconds
for (y in 4 until height step 8) {
for (x in 4 until width step 8) {
val g = gradient3D(::perlinQuintic, 100, x * 0.005, y * 0.005, t, 0.0005).xy
drawer.lineSegment(Vector2(x * 1.0, y * 1.0) - g * 2.0, Vector2(x * 1.0, y * 1.0) + g * 2.0)
}
}
}
}
}
Gradients can also be calculated for the fbm, rigid and billow versions of the noise functions. However, we first have to create a function that can be used by the gradient estimator. For this .fbm()
, .billow()
, and .rigid()
can be used (which works through partial application).
fun main() = application {
program {
val noise = simplex3D.fbm(octaves = 3)
extend {
drawer.fill = null
drawer.stroke = ColorRGBa.PINK
drawer.lineCap = LineCap.ROUND
drawer.strokeWeight = 1.5
val t = seconds
for (y in 4 until height step 8) {
for (x in 4 until width step 8) {
val g = gradient3D(noise, 100, x * 0.002, y * 0.002, t, 0.002).xy
drawer.lineSegment(Vector2(x * 1.0, y * 1.0) - g * 1.0, Vector2(x * 1.0, y * 1.0) + g * 1.0)
}
}
}
}
}
Noise filters
The library contains a number of Filters with which noise image can be generated efficiently on the GPU.
Hash noise
A white-noise-like noise generator.
Parameter | Default value | Description |
---|---|---|
seed | 0.0 | Noise seed |
gain | Vector4(1.0, 1.0, 1.0, 0.0) | Noise gain per channel |
bias | Vector4(0.0, 0.0, 0.0, 1.0) | Value to add to the generated noise |
monochrome | true | Outputs monochrome noise if true |
premultipliedAlpha | true | Outputs premultiplied alpha if true |
fun main() = application {
program {
val cb = colorBuffer(width, height)
val hn = HashNoise()
extend {
hn.seed = seconds
hn.apply(emptyArray(), cb)
drawer.image(cb)
}
}
}
3D Simplex noise filter
The SimplexNoise3D
filter is based on Ken Perlin’s improvement over Perlin noise, but with fewer directional artifacts and, in higher dimensions, a lower computational overhead.
Parameter | Default value | Description |
---|---|---|
seed | Vector3(0.0, 0.0, 0.0) | Noise seed / offset |
scale | Vector3(1.0, 1.0, 1.0) | The noise scale at the first octave |
octaves | 4 | The number of octaves |
gain | Vector4(0.5, 0.5, 0.5, 0.5) | Noise gain per channel per octave |
decay | Vector4(0.5, 0.5, 0.5, 0.5) | Noise decay per channel per octave |
bias | Vector4(0.5, 0.5, 0.5, 0.5) | Value to add to the generated noise |
lacunarity | Vector4(2.0, 2.0, 2.0, 2.0) | Multiplication of noise scale per octave |
premultipliedAlpha | true | Outputs premultiplied alpha if true |
fun main() = application {
program {
val cb = colorBuffer(width, height)
val sn = SimplexNoise3D()
extend {
sn.seed = Vector3(0.0, 0.0, seconds * 0.1)
sn.scale = Vector3.ONE * 2.0
sn.octaves = 8
sn.premultipliedAlpha = false
sn.apply(emptyArray(), cb)
drawer.image(cb)
}
}
}
Cell noise
A cell, Worley or Voronoi noise generator
Parameter | Default value | Description |
---|---|---|
seed | Vector2(0.0, 0.0) | Noise seed / offset |
scale | Vector2(1.0, 1.0) | The noise scale at the first octave |
octaves | 4 | The number of octaves |
gain | Vector4(1.0, 1.0, 1.0, 0.0) | Noise gain per channel per octave |
decay | Vector4(0.5, 0.5, 0.5, 0.5) | Noise decay per channel per octave |
bias | Vector4(0.0, 0.0, 0.0, 1.0) | Value to add to the generated noise |
lacunarity | Vector4(2.0, 2.0, 2.0, 2.0) | Multiplication of noise scale per octave |
premultipliedAlpha | true | Outputs premultiplied alpha if true |
fun main() = application {
program {
val cb = colorBuffer(width, height)
val cn = CellNoise()
extend {
cn.octaves = 4
cn.apply(emptyArray(), cb)
drawer.image(cb)
}
}
}
Speckle noise
A speckle noise generator.
Parameter | Default value | Description |
---|---|---|
color | ColorRGBa.WHITE | Speckle color |
density | 1.0 | Speckle density |
seed | 0.0 | Noise seed |
noise | 0.0 | Speckle noisiness |
premultipliedAlpha | true | Outputs premultiplied alpha if true |
fun main() = application {
program {
val cb = colorBuffer(width, height)
val sn = SpeckleNoise()
extend {
sn.seed = seconds
sn.apply(emptyArray(), cb)
drawer.image(cb)
}
}
}
Value noise
The ValueNoise
filter generates a simple fractal noise. Value noise is a computationally cheap form of creating ‘smooth noise’ by interpolating random values on a lattice.
Parameter | Default value | Description |
---|---|---|
seed | Vector2(0.0, 0.0) | Noise seed / offset |
scale | Vector2(1.0, 1.0) | The noise scale at the first octave |
octaves | 4 | The number of octaves |
gain | Vector4(1.0, 1.0, 1.0, 0.0) | Noise gain per channel per octave |
decay | Vector4(0.5, 0.5, 0.5, 0.5) | Noise decay per channel per octave |
bias | Vector4(0.0, 0.0, 0.0, 1.0) | Value to add to the generated noise |
lacunarity | Vector4(2.0, 2.0, 2.0, 2.0) | Multiplication of noise scale per octave |
premultipliedAlpha | true | Outputs premultiplied alpha if true |
fun main() = application {
program {
val cb = colorBuffer(width, height)
val vn = ValueNoise()
extend {
vn.scale = Vector2.ONE * 4.0
vn.gain = Vector4.ONE * 0.5
vn.octaves = 8
vn.apply(emptyArray(), cb)
drawer.image(cb)
}
}
}