[orx-noise] Add gradient and crossFade tools

This commit is contained in:
Edwin Jakobs
2021-07-26 20:14:30 +02:00
parent 454affbdfd
commit 32e81a82c5
4 changed files with 98 additions and 16 deletions

View File

@@ -1,8 +1,6 @@
package org.openrndr.extra.noise package org.openrndr.extra.noise
import org.openrndr.math.Vector2 import org.openrndr.math.*
import org.openrndr.math.Vector3
import org.openrndr.math.Vector4
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
fun ((Double) -> Double).withSeedAsOffset(offset: Double): (Int, Double) -> Double = { seed, x -> fun ((Double) -> Double).withSeedAsOffset(offset: Double): (Int, Double) -> Double = { seed, x ->
@@ -11,6 +9,46 @@ fun ((Double) -> Double).withSeedAsOffset(offset: Double): (Int, Double) -> Doub
fun ((Int, Double) -> Double).withFixedSeed(seed: Int): (Double) -> Double = { x -> this(seed, x) } fun ((Int, Double) -> Double).withFixedSeed(seed: Int): (Double) -> Double = { x -> this(seed, x) }
fun ((Int, Double) -> Double).gradient(epsilon: Double = 1e-6): (Int, Double) -> Double = { seed, x ->
(this(seed, x + epsilon) - this(seed, x - epsilon)) / (2 * epsilon)
}
fun ((Int, Double, Double) -> Vector2).gradient(epsilon: Double = 1e-6): (Int, Double, Double) -> Vector2 =
{ seed, x, y ->
val dfdx = (this(seed, x + epsilon, y) - this(seed, x - epsilon, y)) / (2 * epsilon)
val dfdy = (this(seed, x, y + epsilon) - this(seed, x, y - epsilon)) / (2 * epsilon)
dfdx + dfdy
}
fun ((Int, Double, Double, Double) -> Double).crossFade(
start: Double,
end: Double,
width: Double = 0.5
): (Int, Double, Double, Double) -> Double {
return { seed, x, y, z ->
val a = z.map(start, end, 0.0, 1.0).mod_(1.0)
val f = (a / width).coerceAtMost(1.0)
val o = this(seed, x, y, a.map(0.0, 1.0, start, end)) * f + (1.0 - f) * this(
seed,
x,
y,
(a + 1.0).map(0.0, 1.0, start, end)
)
o
}
}
fun ((Int, Double, Double, Double) -> Vector2).gradient(epsilon: Double = 1e-2 / 2.0): (Int, Double, Double, Double) -> Vector2 =
{ seed, x, y, z ->
val dfdx = (this(seed, x + epsilon, y, z) - this(seed, x - epsilon, y, z)) / (2 * epsilon)
val dfdy = (this(seed, x, y + epsilon, z) - this(seed, x, y - epsilon, z)) / (2 * epsilon)
dfdx + dfdy
}
fun ((Int, Double) -> Double).scaleBiasOutput( fun ((Int, Double) -> Double).scaleBiasOutput(
scale: Double = 1.0, scale: Double = 1.0,
bias: Double = 0.0 bias: Double = 0.0
@@ -18,7 +56,7 @@ fun ((Int, Double) -> Double).scaleBiasOutput(
this(seed, x) * scale + bias this(seed, x) * scale + bias
} }
fun ((Int, Double) -> Double).mapOutput(map: (Double)->Double): (Int, Double) -> Double = { seed, x -> fun ((Int, Double) -> Double).mapOutput(map: (Double) -> Double): (Int, Double) -> Double = { seed, x ->
map(this(seed, x)) map(this(seed, x))
} }

View File

@@ -37,7 +37,7 @@ fun polarOffsetFunc(
noise: (Int, Double, Double) -> Double, noise: (Int, Double, Double) -> Double,
origin: Vector2 = Vector2.ZERO, origin: Vector2 = Vector2.ZERO,
): (seed: Int, polar: Polar, offset: Vector2) -> Double { ): (seed: Int, polar: Polar, offset: Vector2) -> Double {
return { seed, polar, offset -> return { seed, polar, offset ->
val c = polar.cartesian + origin + offset val c = polar.cartesian + origin + offset
noise(seed, c.x, c.y) noise(seed, c.x, c.y)
@@ -59,14 +59,15 @@ fun ((Int, Vector2) -> Double).withPolarOffsetInput(origin: Vector2 = Vector2.ZE
polarOffsetFunc(this.withScalarInput(), origin) polarOffsetFunc(this.withScalarInput(), origin)
fun ((Int, Double, Double) -> Double).fixedRadiusPolar( fun ((Int, Double, Double) -> Double).fixedRadiusPolar(
radius: Double, radius: Double,
origin: Vector2 = Vector2.ZERO origin: Vector2 = Vector2.ZERO
): (Int, Double) -> Double = ): (Int, Double) -> Double =
fixedRadiusPolarFunc(this, radius, origin) fixedRadiusPolarFunc(this, radius, origin)
private fun example() {
fun example() {
val polarFbmSimplex = polarFunc(noise = fbmFunc2D(noise = ::simplex)) val polarFbmSimplex = polarFunc(noise = fbmFunc2D(noise = ::simplex))
val polarBillowPerlin = polarFunc(noise = billowFunc2D(noise = ::perlin)) val polarBillowPerlin = polarFunc(noise = billowFunc2D(noise = ::perlin))

View File

@@ -1,14 +1,19 @@
package org.openrndr.extra.noise package org.openrndr.extra.noise
import org.openrndr.math.Polar
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2
import kotlin.jvm.JvmName
fun ((Int, Double) -> Double).vector2(): (seed: Int, x: Double) -> Vector2 { @JvmName("polarWithVector2Output")
val ref = this fun ((Int, Polar) -> Double).withVector2Output(): (Int, Polar) -> Vector2 =
return { seed:Int, x:Double -> { seed, polar -> Vector2(this(seed, polar), this(seed xor 0x7f7f7f7f, Polar(-polar.theta, polar.radius))) }
Vector2(ref(-seed, x), ref(seed, -x))
} fun ((Int, Double) -> Double).withVector2Output(): (seed: Int, x: Double) -> Vector2 =
} { seed: Int, x: Double -> Vector2(this(seed, x), this(seed xor 0x7f7f7f7f, -x)) }
fun ((Int, Double, Double) -> Double).withVector2Output(): (seed: Int, x: Double, y: Double) -> Vector2 =
{ seed, x, y -> Vector2(this(seed, x, y), this(seed xor 0x7f7f7f7f, y, -x)) }
fun ((Int, Double, Double, Double) -> Double).withVector2Output(): (seed: Int, x: Double, y: Double, z: Double) -> Vector2 =
{ seed, x, y, z -> Vector2(this(seed, x, y, z), this(seed xor 0x7f7f7f7f, y, -x, z)) }
private fun exampleVector() {
::simplex2D
}

View File

@@ -0,0 +1,38 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.LineJoin
import org.openrndr.extensions.SingleScreenshot
import org.openrndr.extra.noise.simplex
import org.openrndr.extra.noise.simplex1D
import org.openrndr.extra.noise.simplex2D
import org.openrndr.extra.noise.simplex3D
import org.openrndr.extra.noise.withVector2Output
import org.openrndr.extra.noise.gradient
import org.openrndr.shape.contour
suspend fun main() = application {
configure {
width = 720
height = 720
}
program {
if (System.getProperty("takeScreenshot") == "true") {
extend(SingleScreenshot()) {
this.outputFile = System.getProperty("screenshotPath")
}
}
val n = simplex3D.withVector2Output().gradient()
extend {
drawer.stroke = null
drawer.fill = ColorRGBa.PINK
drawer.lineJoin = LineJoin.ROUND
drawer.stroke = ColorRGBa.WHITE
for (y in 0 until height step 20) {
for (x in 0 until width step 20) {
val d = n(40, x * 0.003, y * 0.003,seconds) * 5.0
drawer.lineSegment(x * 1.0, y * 1.0, x * 1.0 + d.x, y * 1.0 + d.y)
}
}
}
}
}