From 51096e50f6b85fb11d01ac029bf30c6007769a12 Mon Sep 17 00:00:00 2001 From: Abe Pazos Date: Thu, 20 Oct 2022 19:15:32 +0000 Subject: [PATCH] [orx-noise] Bring back GLSL NoiseFilters.kt (#277) --- .../shaders/glsl/blur/directional-blur.frag | 2 - orx-noise/build.gradle.kts | 18 ++ .../commonMain/kotlin/filters/CellNoise.kt | 71 +++++ .../commonMain/kotlin/filters/HashNoise.kt | 48 ++++ .../commonMain/kotlin/filters/NoiseFilters.kt | 271 ------------------ .../kotlin/filters/SimplexNoise3D.kt | 71 +++++ .../commonMain/kotlin/filters/SpeckleNoise.kt | 55 ++++ .../commonMain/kotlin/filters/ValueNoise.kt | 71 +++++ .../commonMain/kotlin/filters/WorleyNoise.kt | 30 ++ .../kotlin/DemoFunctionalComposition01.kt | 8 +- orx-noise/src/demo/kotlin/DemoNoisesGLSL.kt | 66 +++++ .../src/demo/kotlin/DemoNoisesGLSLGui.kt | 34 +++ orx-noise/src/demo/kotlin/DemoSimplexGLSL.kt | 47 +++ orx-noise/src/shaders/glsl/noise/cell.frag | 54 ++++ orx-noise/src/shaders/glsl/noise/hash.frag | 29 ++ .../src/shaders/glsl/noise/simplex3D.frag | 139 +++++++++ orx-noise/src/shaders/glsl/noise/speckle.frag | 33 +++ orx-noise/src/shaders/glsl/noise/value.frag | 52 ++++ orx-noise/src/shaders/glsl/noise/worley.frag | 72 +++++ 19 files changed, 891 insertions(+), 280 deletions(-) create mode 100644 orx-noise/src/commonMain/kotlin/filters/CellNoise.kt create mode 100644 orx-noise/src/commonMain/kotlin/filters/HashNoise.kt delete mode 100644 orx-noise/src/commonMain/kotlin/filters/NoiseFilters.kt create mode 100644 orx-noise/src/commonMain/kotlin/filters/SimplexNoise3D.kt create mode 100644 orx-noise/src/commonMain/kotlin/filters/SpeckleNoise.kt create mode 100644 orx-noise/src/commonMain/kotlin/filters/ValueNoise.kt create mode 100644 orx-noise/src/commonMain/kotlin/filters/WorleyNoise.kt create mode 100644 orx-noise/src/demo/kotlin/DemoNoisesGLSL.kt create mode 100644 orx-noise/src/demo/kotlin/DemoNoisesGLSLGui.kt create mode 100644 orx-noise/src/demo/kotlin/DemoSimplexGLSL.kt create mode 100644 orx-noise/src/shaders/glsl/noise/cell.frag create mode 100644 orx-noise/src/shaders/glsl/noise/hash.frag create mode 100644 orx-noise/src/shaders/glsl/noise/simplex3D.frag create mode 100644 orx-noise/src/shaders/glsl/noise/speckle.frag create mode 100644 orx-noise/src/shaders/glsl/noise/value.frag create mode 100644 orx-noise/src/shaders/glsl/noise/worley.frag diff --git a/orx-fx/src/shaders/glsl/blur/directional-blur.frag b/orx-fx/src/shaders/glsl/blur/directional-blur.frag index 3e0803e4..8fc88873 100644 --- a/orx-fx/src/shaders/glsl/blur/directional-blur.frag +++ b/orx-fx/src/shaders/glsl/blur/directional-blur.frag @@ -9,9 +9,7 @@ uniform sampler2D tex1; // blurDirection uniform vec2 textureSize0; uniform int window; -uniform float sigma; uniform float gain; -uniform vec4 subtract; uniform float spread; uniform bool wrapX; diff --git a/orx-noise/build.gradle.kts b/orx-noise/build.gradle.kts index d7cdc92b..97fada4d 100644 --- a/orx-noise/build.gradle.kts +++ b/orx-noise/build.gradle.kts @@ -4,6 +4,14 @@ plugins { org.openrndr.extra.convention.`kotlin-multiplatform` } +val embedShaders = tasks.register("embedShaders") { + inputDir.set(file("$projectDir/src/shaders/glsl")) + outputDir.set(file("$buildDir/generated/shaderKotlin")) + defaultPackage.set("org.openrndr.extra.noise.filters") + defaultVisibility.set("internal") + namePrefix.set("noise_") +}.get() + kotlin { jvm { @Suppress("UNUSED_VARIABLE") @@ -22,6 +30,10 @@ kotlin { } sourceSets { + val shaderKotlin by creating { + this.kotlin.srcDir(embedShaders.outputDir) + } + @Suppress("UNUSED_VARIABLE") val commonMain by getting { dependencies { @@ -29,7 +41,11 @@ kotlin { implementation(libs.openrndr.shape) implementation(libs.openrndr.draw) implementation(project(":orx-hash-grid")) + implementation(project(":orx-parameters")) + implementation(project(":orx-shader-phrases")) + api(shaderKotlin.kotlin) } + dependsOn(shaderKotlin) } @@ -46,6 +62,8 @@ kotlin { val jvmDemo by getting { dependencies { implementation(project(":orx-hash-grid")) + implementation(project(":orx-noise")) + implementation(project(":orx-jvm:orx-gui")) } } } diff --git a/orx-noise/src/commonMain/kotlin/filters/CellNoise.kt b/orx-noise/src/commonMain/kotlin/filters/CellNoise.kt new file mode 100644 index 00000000..80b214c3 --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/filters/CellNoise.kt @@ -0,0 +1,71 @@ +package org.openrndr.extra.noise.filters + +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromCode +import org.openrndr.extra.parameters.* +import org.openrndr.extra.shaderphrases.preprocess +import org.openrndr.math.Vector2 +import org.openrndr.math.Vector4 + +/** + * Filter that produces cell or Voronoi noise + */ +@Description("Cell Noise") +class CellNoise : Filter(filterShaderFromCode(run { + noise_cell.preprocess() +}, "cell-noise")) { + @Vector2Parameter("Seed", -10.0, 10.0) + var seed: Vector2 by parameters + + /** + * base noise scale, default is Vector2(1.0, 1.0) + */ + @Vector2Parameter("Scale", 0.01, 10.0) + var scale: Vector2 by parameters + + /** + * lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0) + */ + @Vector2Parameter("Lacunarity", 0.1, 5.0) + var lacunarity: Vector2 by parameters + + /** + * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0) + */ + @Vector4Parameter("Gain", 0.0, 1.0) + var gain: Vector4 by parameters + + /** + * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5) + */ + @Vector4Parameter("Decay", 0.0, 1.0) + var decay: Vector4 by parameters + + /** + * the number of octaves of noise to generate, default is 4 + */ + @IntParameter("Octaves", 1, 8) + var octaves: Int by parameters + + /** + * the value to add to the resulting noise + */ + @Vector4Parameter("Bias", -1.0, 1.0) + var bias: Vector4 by parameters + + /** + * should the output colors be multiplied by the alpha channel, default is true + */ + var premultipliedAlpha: Boolean by parameters + + init { + seed = Vector2.ZERO + scale = Vector2.ONE + lacunarity = Vector2(2.0, 2.0) + gain = Vector4.ONE + decay = Vector4.ONE / 2.0 + octaves = 4 + bias = Vector4.ZERO + premultipliedAlpha = true + } +} \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/filters/HashNoise.kt b/orx-noise/src/commonMain/kotlin/filters/HashNoise.kt new file mode 100644 index 00000000..e5fe9adc --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/filters/HashNoise.kt @@ -0,0 +1,48 @@ +package org.openrndr.extra.noise.filters + +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromCode +import org.openrndr.extra.parameters.* +import org.openrndr.extra.shaderphrases.preprocess +import org.openrndr.math.Vector4 + +/** + * Hash noise filter that produces white-noise-like noise. + */ +@Description("Hash Noise") +class HashNoise : Filter(filterShaderFromCode(run { + noise_hash.preprocess() +}, "hash-noise")) { + /** + * noise gain per channel, default is Vector4(1.0, 1.0, 1.0, 0.0) + */ + @Vector4Parameter("Gain") + var gain: Vector4 by parameters + + /** + * noise bias per channel, default is Vector4(0.0, 0.0, 0.0, 1.0) + */ + @Vector4Parameter("Bias") + var bias: Vector4 by parameters + + /** + * is the noise monochrome, default is true + */ + @BooleanParameter("Monochrome") + var monochrome: Boolean by parameters + + /** + * noise seed, feed it with time to animate + */ + @DoubleParameter("Seed", 0.0, 1000.0) + var seed: Double by parameters + + init { + monochrome = true + gain = Vector4(1.0, 1.0, 1.0, 0.0) + bias = Vector4(0.0, 0.0, 0.0, 1.0) + seed = 0.0 + } +} + + diff --git a/orx-noise/src/commonMain/kotlin/filters/NoiseFilters.kt b/orx-noise/src/commonMain/kotlin/filters/NoiseFilters.kt deleted file mode 100644 index 82a48f39..00000000 --- a/orx-noise/src/commonMain/kotlin/filters/NoiseFilters.kt +++ /dev/null @@ -1,271 +0,0 @@ -//package org.openrndr.extra.noise.filters -// -//import org.openrndr.color.ColorRGBa -//import org.openrndr.draw.Filter -//import org.openrndr.draw.filterShaderFromUrl -//import org.openrndr.extra.parameters.* -//import org.openrndr.math.Vector2 -//import org.openrndr.math.Vector3 -//import org.openrndr.math.Vector4 -//import org.openrndr.resourceUrl -// -///** -// * Hash noise filter that produces white-noise-like noise. -// */ -//class HashNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/hash-noise.frag"))) { -// /** -// * noise gain per channel, default is Vector4(1.0, 1.0, 1.0, 0.0) -// */ -// var gain: Vector4 by parameters -// -// /** -// * noise bias per channel, default is Vector4(0.0, 0.0, 0.0, 1.0) -// */ -// var bias: Vector4 by parameters -// -// /** -// * is the noise monochrome, default is true -// */ -// @BooleanParameter("Monochrome") -// var monochrome: Boolean by parameters -// -// /** -// * noise seed, feed it with time to animate -// */ -// @DoubleParameter("Seed", 0.0, 10000.0) -// var seed: Double by parameters -// -// init { -// monochrome = true -// gain = Vector4(1.0, 1.0, 1.0, 0.0) -// bias = Vector4(0.0, 0.0, 0.0, 1.0) -// seed = 0.0 -// } -//} -// -///** -// * Speckle noise filter -// */ -//class SpeckleNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/speckle-noise.frag"))) { -// -// /** -// * The color of the generated speckles -// */ -// @ColorParameter("Color") -// var color: ColorRGBa by parameters -// -// /** -// * Density of the speckles, default is 0.1, min, 0.0, max is 1.0 -// */ -// @DoubleParameter("Density", 0.0, 1.0) -// var density: Double by parameters -// -// -// /** -// * Noisiness of the generated speckles, default is 0.0, min is 0.0, max is 1.0 -// */ -// @DoubleParameter("Noise", 0.0, 1.0) -// var noise: Double by parameters -// -// /** -// * should the output colors be multiplied by the alpha channel, default is true -// */ -// var premultipliedAlpha: Boolean by parameters -// -// /** -// * noise seed, feed it with time to animate -// */ -// @DoubleParameter("Seed", 0.0, 10000.0) -// var seed: Double by parameters -// -// init { -// density = 0.1 -// color = ColorRGBa.WHITE -// seed = 0.0 -// noise = 0.0 -// premultipliedAlpha = true -// } -//} -// -///** -// * Filter that produces cell or Voronoi noise -// */ -//class CellNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/cell-noise.frag"))) { -// var seed: Vector2 by parameters -// -// /** -// * base noise scale, default is Vector2(1.0, 1.0) -// */ -// var scale: Vector2 by parameters -// -// /** -// * lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0) -// */ -// var lacunarity: Vector2 by parameters -// -// /** -// * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0) -// */ -// var gain: Vector4 by parameters -// -// /** -// * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5) -// */ -// var decay: Vector4 by parameters -// -// /** -// * the number of octaves of noise to generate, default is 4 -// */ -// @IntParameter("Octaves", 1, 8) -// var octaves: Int by parameters -// -// /** -// * the value to add to the resulting noise -// */ -// var bias: Vector4 by parameters -// -// /** -// * should the output colors be multiplied by the alpha channel, default is true -// */ -// var premultipliedAlpha: Boolean by parameters -// -// init { -// seed = Vector2.ZERO -// scale = Vector2.ONE -// lacunarity = Vector2(2.0, 2.0) -// gain = Vector4.ONE -// decay = Vector4.ONE / 2.0 -// octaves = 4 -// bias = Vector4.ZERO -// premultipliedAlpha = true -// } -//} -// -///** -// * Filter that produces value noise -// */ -//class ValueNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/value-noise.frag"))) { -// @DoubleParameter("Seed", 0.0, 10000.0) -// var seed: Vector2 by parameters -// -// /** -// * base noise scale, default is Vector2(1.0, 1.0) -// */ -// var scale: Vector2 by parameters -// -// /** -// * lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0) -// */ -// var lacunarity: Vector2 by parameters -// -// /** -// * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0) -// */ -// var gain: Vector4 by parameters -// -// /** -// * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5) -// */ -// var decay: Vector4 by parameters -// -// /** -// * the number of octaves of noise to generate, default is 4 -// */ -// @IntParameter("Octaves", 1, 8) -// var octaves: Int by parameters -// -// /** -// * the value to add to the resulting noise -// */ -// var bias: Vector4 by parameters -// -// /** -// * should the output colors be multiplied by the alpha channel, default is true -// */ -// var premultipliedAlpha: Boolean by parameters -// -// init { -// seed = Vector2.ZERO -// scale = Vector2.ONE -// lacunarity = Vector2(2.0, 2.0) -// gain = Vector4.ONE -// decay = Vector4.ONE / 2.0 -// octaves = 4 -// bias = Vector4.ZERO -// premultipliedAlpha = true -// } -//} -// -///** -// * Filter that produces 3D Simplex Noise -// */ -//@Description("Simplex Noise") -//class SimplexNoise3D : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/simplex-noise-3d.frag"))) { -// var seed: Vector3 by parameters -// -// /** -// * base noise scale, default is Vector3(1.0, 1.0, 1.0) -// */ -// var scale: Vector3 by parameters -// -// /** -// * lacunarity is the amount by which scale is modulated per octave, default is Vector3(2.0, 2.0, 2.0) -// */ -// var lacunarity: Vector3 by parameters -// -// /** -// * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0) -// */ -// var gain: Vector4 by parameters -// -// /** -// * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5) -// */ -// var decay: Vector4 by parameters -// -// /** -// * the number of octaves of noise to generate, default is 4 -// */ -// @IntParameter("Octaves", 1, 8) -// var octaves: Int by parameters -// -// /** -// * the value to add to the resulting noise -// */ -// var bias: Vector4 by parameters -// -// /** -// * should the output colors be multiplied by the alpha channel, default is true -// */ -// @BooleanParameter("Premultiplied alpha") -// var premultipliedAlpha: Boolean by parameters -// -// init { -// seed = Vector3.ZERO -// scale = Vector3.ONE -// lacunarity = Vector3(2.0, 2.0, 2.0) -// gain = Vector4.ONE / 2.0 -// decay = Vector4.ONE / 2.0 -// octaves = 4 -// bias = Vector4.ONE / 2.0 -// premultipliedAlpha = true -// } -//} -// -// -///** -// * Filter for Worley Noise -// */ -//@Description("Worley Noise") -//class WorleyNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/worley-noise.frag"))) { -// @DoubleParameter("Scale", 0.1, 200.0) -// var scale: Double by parameters -// -// @BooleanParameter("Premultiplied alpha") -// var premultipliedAlpha: Boolean by parameters -// -// init { -// premultipliedAlpha = true -// scale = 5.0 -// } -//} diff --git a/orx-noise/src/commonMain/kotlin/filters/SimplexNoise3D.kt b/orx-noise/src/commonMain/kotlin/filters/SimplexNoise3D.kt new file mode 100644 index 00000000..e41054c5 --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/filters/SimplexNoise3D.kt @@ -0,0 +1,71 @@ +package org.openrndr.extra.noise.filters + +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromCode +import org.openrndr.extra.parameters.* +import org.openrndr.extra.shaderphrases.preprocess +import org.openrndr.math.Vector3 +import org.openrndr.math.Vector4 + +/** + * Filter that produces 3D Simplex Noise + */ +@Description("Simplex Noise") +class SimplexNoise3D : Filter(filterShaderFromCode(run { + noise_simplex3D.preprocess() +}, "simplex-noise-3d")) { + var seed: Vector3 by parameters + + /** + * base noise scale, default is Vector3(1.0, 1.0, 1.0) + */ + @Vector3Parameter("Scale", 0.0, 5.0) + var scale: Vector3 by parameters + + /** + * lacunarity is the amount by which scale is modulated per octave, default is Vector3(2.0, 2.0, 2.0) + */ + @Vector3Parameter("Lacunarity", 0.0, 5.0) + var lacunarity: Vector3 by parameters + + /** + * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0) + */ + @Vector4Parameter("Gain", 0.0, 1.0) + var gain: Vector4 by parameters + + /** + * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5) + */ + @Vector4Parameter("Decay", 0.0, 1.0) + var decay: Vector4 by parameters + + /** + * the number of octaves of noise to generate, default is 4 + */ + @IntParameter("Octaves", 1, 8) + var octaves: Int by parameters + + /** + * the value to add to the resulting noise + */ + @Vector4Parameter("Bias", -1.0, 1.0) + var bias: Vector4 by parameters + + /** + * should the output colors be multiplied by the alpha channel, default is true + */ + @BooleanParameter("Premultiplied alpha") + var premultipliedAlpha: Boolean by parameters + + init { + seed = Vector3.ZERO + scale = Vector3.ONE + lacunarity = Vector3(2.0, 2.0, 2.0) + gain = Vector4.ONE / 2.0 + decay = Vector4.ONE / 2.0 + octaves = 4 + bias = Vector4.ONE / 2.0 + premultipliedAlpha = true + } +} \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/filters/SpeckleNoise.kt b/orx-noise/src/commonMain/kotlin/filters/SpeckleNoise.kt new file mode 100644 index 00000000..037c4e24 --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/filters/SpeckleNoise.kt @@ -0,0 +1,55 @@ +package org.openrndr.extra.noise.filters + +import org.openrndr.color.ColorRGBa +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromCode +import org.openrndr.extra.parameters.ColorParameter +import org.openrndr.extra.parameters.Description +import org.openrndr.extra.parameters.DoubleParameter +import org.openrndr.extra.shaderphrases.preprocess + +/** + * Speckle noise filter + */ +@Description("Speckle Noise") +class SpeckleNoise : Filter(filterShaderFromCode(run { + noise_speckle.preprocess() +}, "speckle-noise")) { + + /** + * The color of the generated speckles + */ + @ColorParameter("Color") + var color: ColorRGBa by parameters + + /** + * Density of the speckles, default is 0.1, min, 0.0, max is 1.0 + */ + @DoubleParameter("Density", 0.0, 1.0) + var density: Double by parameters + + /** + * Noisiness of the generated speckles, default is 0.0, min is 0.0, max is 1.0 + */ + @DoubleParameter("Noise", 0.0, 1.0) + var noise: Double by parameters + + /** + * should the output colors be multiplied by the alpha channel, default is true + */ + var premultipliedAlpha: Boolean by parameters + + /** + * noise seed, feed it with time to animate + */ + @DoubleParameter("Seed", 0.0, 1000.0) + var seed: Double by parameters + + init { + density = 0.1 + color = ColorRGBa.WHITE + seed = 0.0 + noise = 0.0 + premultipliedAlpha = true + } +} \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/filters/ValueNoise.kt b/orx-noise/src/commonMain/kotlin/filters/ValueNoise.kt new file mode 100644 index 00000000..e181509d --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/filters/ValueNoise.kt @@ -0,0 +1,71 @@ +package org.openrndr.extra.noise.filters + +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromCode +import org.openrndr.extra.parameters.* +import org.openrndr.extra.shaderphrases.preprocess +import org.openrndr.math.Vector2 +import org.openrndr.math.Vector4 + +/** + * Filter that produces value noise + */ +@Description("Value Noise") +class ValueNoise : Filter(filterShaderFromCode(run { + noise_value.preprocess() +}, "value-noise")) { + @Vector2Parameter("Seed", 0.0, 10000.0) + var seed: Vector2 by parameters + + /** + * base noise scale, default is Vector2(1.0, 1.0) + */ + @Vector2Parameter("Scale", 0.0, 5.0) + var scale: Vector2 by parameters + + /** + * lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0) + */ + @Vector2Parameter("Lacunarity", 0.0, 5.0) + var lacunarity: Vector2 by parameters + + /** + * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0) + */ + @Vector4Parameter("Gain", 0.0, 1.0) + var gain: Vector4 by parameters + + /** + * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5) + */ + @Vector4Parameter("Decay", 0.0, 1.0) + var decay: Vector4 by parameters + + /** + * the number of octaves of noise to generate, default is 4 + */ + @IntParameter("Octaves", 1, 8) + var octaves: Int by parameters + + /** + * the value to add to the resulting noise + */ + @Vector4Parameter("Bias", -1.0, 1.0) + var bias: Vector4 by parameters + + /** + * should the output colors be multiplied by the alpha channel, default is true + */ + var premultipliedAlpha: Boolean by parameters + + init { + seed = Vector2.ZERO + scale = Vector2.ONE + lacunarity = Vector2(2.0, 2.0) + gain = Vector4.ONE + decay = Vector4.ONE / 2.0 + octaves = 4 + bias = Vector4.ZERO + premultipliedAlpha = true + } +} \ No newline at end of file diff --git a/orx-noise/src/commonMain/kotlin/filters/WorleyNoise.kt b/orx-noise/src/commonMain/kotlin/filters/WorleyNoise.kt new file mode 100644 index 00000000..4041e798 --- /dev/null +++ b/orx-noise/src/commonMain/kotlin/filters/WorleyNoise.kt @@ -0,0 +1,30 @@ +package org.openrndr.extra.noise.filters + +import org.openrndr.draw.Filter +import org.openrndr.draw.filterShaderFromCode +import org.openrndr.extra.parameters.* +import org.openrndr.extra.shaderphrases.preprocess +import org.openrndr.math.Vector2 + +/** + * Filter for Worley Noise + */ +@Description("Worley Noise") +class WorleyNoise : Filter(filterShaderFromCode(run { + noise_worley.preprocess() +}, "worley-noise")) { + @DoubleParameter("Scale", 0.1, 200.0) + var scale: Double by parameters + + @BooleanParameter("Premultiplied alpha") + var premultipliedAlpha: Boolean by parameters + + @Vector2Parameter("Offset") + var offset: Vector2 by parameters + + init { + premultipliedAlpha = true + scale = 5.0 + offset = Vector2.ZERO + } +} \ No newline at end of file diff --git a/orx-noise/src/demo/kotlin/DemoFunctionalComposition01.kt b/orx-noise/src/demo/kotlin/DemoFunctionalComposition01.kt index bb76496d..c079266c 100644 --- a/orx-noise/src/demo/kotlin/DemoFunctionalComposition01.kt +++ b/orx-noise/src/demo/kotlin/DemoFunctionalComposition01.kt @@ -1,15 +1,9 @@ import org.openrndr.application import org.openrndr.color.ColorRGBa import org.openrndr.draw.LineJoin -import org.openrndr.extensions.SingleScreenshot -import org.openrndr.extra.noise.perturb -import org.openrndr.extra.noise.simplex -import org.openrndr.extra.noise.simplex1D -import org.openrndr.extra.noise.simplex2D +import org.openrndr.extra.noise.gradient import org.openrndr.extra.noise.simplex3D import org.openrndr.extra.noise.withVector2Output -import org.openrndr.extra.noise.gradient -import org.openrndr.shape.contour fun main() = application { configure { diff --git a/orx-noise/src/demo/kotlin/DemoNoisesGLSL.kt b/orx-noise/src/demo/kotlin/DemoNoisesGLSL.kt new file mode 100644 index 00000000..2dd28de4 --- /dev/null +++ b/orx-noise/src/demo/kotlin/DemoNoisesGLSL.kt @@ -0,0 +1,66 @@ +import org.openrndr.application +import org.openrndr.draw.colorBuffer +import org.openrndr.extra.noise.filters.* +import org.openrndr.math.Vector2 +import org.openrndr.math.Vector3 +import org.openrndr.math.Vector4 +import kotlin.math.sin + +/** + * Render existing GLSL noise algorithms side by side. + * Re-use the same color buffer for the rendering. + * Not all noise properties are used. Explore each noise class + * to find out more adjustable properties. + * The noise color can be set using a `color` or a `gain` property. + */ +fun main() = application { + program { + val noises = listOf( + HashNoise(), SpeckleNoise(), CellNoise(), + ValueNoise(), SimplexNoise3D(), WorleyNoise() + ) + + val img = colorBuffer(width / noises.size, height * 8 / 10) + + extend { + val seed = seconds * 0.1 + val scale = 1.0 + sin(seed) * 0.5 + noises.forEach { noise -> + when (noise) { + is HashNoise -> { + noise.seed = seed + noise.gain = Vector4(0.5 + sin(seconds) * 0.5) + noise.monochrome = frameCount % 100 < 50 + } + is SpeckleNoise -> { + noise.seed = seed + noise.density = 0.1 + sin(seconds) * 0.1 + } + is CellNoise -> { + noise.seed = Vector2(seed) + noise.scale = Vector2(scale) + } + is ValueNoise -> { + noise.seed = Vector2(seed) + noise.scale = Vector2(scale) + noise.gain = Vector4(0.5) + } + is SimplexNoise3D -> { + noise.seed = Vector3(seed) + noise.scale = Vector3(scale) + } + is WorleyNoise -> { + noise.scale = scale + noise.offset = Vector2(seed) + } + } + noise.apply(emptyArray(), img) + drawer.image(img) + drawer.translate( + width / noises.size * 1.0, + height * 2 / 10 / (noises.size - 1.0) + ) + } + } + } +} \ No newline at end of file diff --git a/orx-noise/src/demo/kotlin/DemoNoisesGLSLGui.kt b/orx-noise/src/demo/kotlin/DemoNoisesGLSLGui.kt new file mode 100644 index 00000000..07cf207e --- /dev/null +++ b/orx-noise/src/demo/kotlin/DemoNoisesGLSLGui.kt @@ -0,0 +1,34 @@ +import org.openrndr.application +import org.openrndr.draw.colorBuffer +import org.openrndr.extra.gui.GUI +import org.openrndr.extra.noise.filters.* + +/** + * Render existing GLSL noise algorithms side by side. + * Use the GUI to explore the effects. + */ +fun main() = application { + configure { + width = 200 * 6 + 200 + height = 500 + } + program { + val noises = listOf( + HashNoise(), SpeckleNoise(), CellNoise(), + ValueNoise(), SimplexNoise3D(), WorleyNoise() + ) + + val img = colorBuffer(200, 460) + + val gui = GUI() + noises.forEach { gui.add(it) } + extend(gui) + + extend { + noises.forEachIndexed { i, noise -> + noise.apply(emptyArray(), img) + drawer.image(img, 200.0 + i * 200.0, 20.0) + } + } + } +} \ No newline at end of file diff --git a/orx-noise/src/demo/kotlin/DemoSimplexGLSL.kt b/orx-noise/src/demo/kotlin/DemoSimplexGLSL.kt new file mode 100644 index 00000000..ba5c4370 --- /dev/null +++ b/orx-noise/src/demo/kotlin/DemoSimplexGLSL.kt @@ -0,0 +1,47 @@ +import org.openrndr.application +import org.openrndr.color.rgb +import org.openrndr.draw.colorBuffer +import org.openrndr.extra.noise.Random +import org.openrndr.extra.noise.filters.* +import org.openrndr.math.Vector3 +import org.openrndr.math.Vector4 +import kotlin.math.sin + +/** + * A sine oscillator with randomized parameters + */ +class SinOsc { + private val freq = Random.double(0.1, 2.0) + private val phase = Random.double(0.0, 6.28) + private val add = Random.double(0.0, 1.0) + private val mul = Random.double(0.0, 1.0 - add) + operator fun invoke() = sin(System.currentTimeMillis() * 0.0001 * freq + phase) * mul + add +} + +/** + * Render an animated Simplex3D texture using shaders. + * + * The uniforms in the shader are controlled by + * randomized sine oscillators. + */ +fun main() = application { + program { + val noise = SimplexNoise3D() + val img = colorBuffer(width, height) + val wav = List(21) { SinOsc() } + + extend { + noise.seed = Vector3(wav[0](), wav[1](), wav[2]()) // = position + noise.scale = Vector3(wav[3](), wav[4](), wav[5]()) + noise.lacunarity = Vector3(wav[6](), wav[7](), wav[8]()) + noise.gain = Vector4(wav[9](), wav[10](), wav[11](), wav[12]()) + noise.decay = Vector4(wav[13](), wav[14](), wav[15](), wav[16]()) + noise.octaves = 4 + noise.bias = Vector4(wav[17](), wav[18](), wav[19](), wav[20]()) + + noise.apply(emptyArray(), img) + drawer.clear(rgb(0.20, 0.18, 0.16)) + drawer.image(img) + } + } +} diff --git a/orx-noise/src/shaders/glsl/noise/cell.frag b/orx-noise/src/shaders/glsl/noise/cell.frag new file mode 100644 index 00000000..d4acfd33 --- /dev/null +++ b/orx-noise/src/shaders/glsl/noise/cell.frag @@ -0,0 +1,54 @@ +// uniforms +uniform vec4 gain; +uniform vec4 bias; +uniform vec2 seed; + +uniform vec2 scale; +uniform vec2 lacunarity; +uniform vec4 decay; +uniform int octaves; +uniform bool premultipliedAlpha; + +// varyings +in vec2 v_texCoord0; + +// outputs +out vec4 o_output; + +vec2 hash22(vec2 p) { + float n = sin(dot(p, vec2(41, 289))); + return fract(vec2(262144, 32768)*n); +} + +float cell(vec2 p) { + vec2 ip = floor(p); + p = fract(p); + + float d = 1.0; + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + vec2 cellRef = vec2(i, j); + vec2 offset = hash22(ip + cellRef); + vec2 r = cellRef + offset - p; + float d2 = dot(r, r); + d = min(d, d2); + } + } + return d; +} + +void main() { + vec4 result = vec4(0.0); + vec4 _gain = gain; + vec2 _scale = scale; + for (int o = 0; o < octaves; ++o) { + result += cell((v_texCoord0+seed) * _scale) * _gain; + _scale *= lacunarity; + _gain *= decay; + } + o_output = result + bias; + + if (premultipliedAlpha) { + o_output.rgb *= o_output.a; + } +} diff --git a/orx-noise/src/shaders/glsl/noise/hash.frag b/orx-noise/src/shaders/glsl/noise/hash.frag new file mode 100644 index 00000000..e7c8a409 --- /dev/null +++ b/orx-noise/src/shaders/glsl/noise/hash.frag @@ -0,0 +1,29 @@ +// uniforms +uniform vec4 gain; +uniform vec4 bias; +uniform bool monochrome; +uniform float seed; + +// varyings +in vec2 v_texCoord0; + +// outputs +out vec4 o_output; + +vec2 hash22(vec2 p) { + float n = sin(dot(p, vec2(41, 289))); + return fract(vec2(262144, 32768)*n); +} + +void main() { + + vec2 vseed = vec2(seed); + if (!monochrome) { + o_output.rg = hash22(vseed + v_texCoord0) * gain.rg + bias.rg; + o_output.ba = hash22(vseed + v_texCoord0+vec2(1.0, 1.0)) * gain.ba + bias.ba; + } else { + float c = hash22(vseed + v_texCoord0).r; + o_output = c * gain + bias; + } + +} diff --git a/orx-noise/src/shaders/glsl/noise/simplex3D.frag b/orx-noise/src/shaders/glsl/noise/simplex3D.frag new file mode 100644 index 00000000..ddc5c0d9 --- /dev/null +++ b/orx-noise/src/shaders/glsl/noise/simplex3D.frag @@ -0,0 +1,139 @@ +// uniforms +uniform vec4 gain; +uniform vec4 bias; +uniform vec3 seed; +uniform vec3 scale; + +uniform vec3 lacunarity; +uniform vec4 decay; +uniform int octaves; +uniform bool premultipliedAlpha; + +// varyings +in vec2 v_texCoord0; + +// outputs +out vec4 o_output; + +// Simplex Noise 3D Implementation +// Description : Array and textureless GLSL 2D/3D/4D simplex +// noise functions. +// Author : Ian McEwan, Ashima Arts. +// Maintainer : ijm +// Lastmod : 20110822 (ijm) +// License : Copyright (C) 2011 Ashima Arts. All rights reserved. +// Distributed under the MIT License. See LICENSE file. +// https://github.com/ashima/webgl-noise +// https://github.com/stegu/webgl-noise +// +// +vec3 mod289(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 mod289(vec4 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 permute(vec4 x) { + return mod289(((x*34.0)+1.0)*x); +} + +vec4 taylorInvSqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} + +float snoise(vec3 v) { + const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; + const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); + + // First corner + vec3 i = floor(v + dot(v, C.yyy) ); + vec3 x0 = v - i + dot(i, C.xxx) ; + + // Other corners + vec3 g = step(x0.yzx, x0.xyz); + vec3 l = 1.0 - g; + vec3 i1 = min( g.xyz, l.zxy ); + vec3 i2 = max( g.xyz, l.zxy ); + + // x0 = x0 - 0.0 + 0.0 * C.xxx; + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + vec3 x1 = x0 - i1 + C.xxx; + vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y + vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = mod289(i); + vec4 p = permute( permute( permute( + i.z + vec4(0.0, i1.z, i2.z, 1.0 )) + + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) + + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + float n_ = 0.142857142857; // 1.0/7.0 + vec3 ns = n_ * D.wyz - D.xzx; + + vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) + + vec4 x_ = floor(j * ns.z); + vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) + + vec4 x = x_ *ns.x + ns.yyyy; + vec4 y = y_ *ns.x + ns.yyyy; + vec4 h = 1.0 - abs(x) - abs(y); + + vec4 b0 = vec4( x.xy, y.xy ); + vec4 b1 = vec4( x.zw, y.zw ); + + //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; + //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; + vec4 s0 = floor(b0)*2.0 + 1.0; + vec4 s1 = floor(b1)*2.0 + 1.0; + vec4 sh = -step(h, vec4(0.0)); + + vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; + vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; + + vec3 p0 = vec3(a0.xy,h.x); + vec3 p1 = vec3(a0.zw,h.y); + vec3 p2 = vec3(a1.xy,h.z); + vec3 p3 = vec3(a1.zw,h.w); + + //Normalise gradients + vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); + m = m * m; + return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), + dot(p2,x2), dot(p3,x3) ) ); +} + +void main() { + vec4 result = vec4(0.0); + vec4 _gain = gain; + + vec3 shift = vec3(100); + vec3 uv = vec3(v_texCoord0, 1.0) * 2.0 - 1.0; + vec3 x = ((uv + seed) * scale); + + for (int o = 0; o < octaves; ++o) { + result += snoise(x) * _gain; + x = x * lacunarity + shift; + _gain *= decay; + } + + o_output = result + bias; + + if (premultipliedAlpha) { + o_output.rgb *= o_output.a; + } +} \ No newline at end of file diff --git a/orx-noise/src/shaders/glsl/noise/speckle.frag b/orx-noise/src/shaders/glsl/noise/speckle.frag new file mode 100644 index 00000000..a1adba5b --- /dev/null +++ b/orx-noise/src/shaders/glsl/noise/speckle.frag @@ -0,0 +1,33 @@ +// uniforms +uniform float seed; +uniform float density; +uniform vec4 color; +uniform bool premultipliedAlpha; +uniform float noise; + +// varyings +in vec2 v_texCoord0; + +// outputs +out vec4 o_output; + +vec2 hash22(vec2 p) { + float n = sin(dot(p, vec2(41, 289))); + return fract(vec2(262144, 32768)*n); +} + +void main() { + vec2 vseed = vec2(seed); + vec2 hash = hash22(v_texCoord0 + seed); + float t = hash.x; + + vec4 result = vec4(0.0); + if (t < density) { + vec4 noisyColor = vec4(color.rgb * mix(1.0, hash.y, noise), color.a); + result = noisyColor; + } + o_output = result; + if (premultipliedAlpha) { + o_output.rgb *= o_output.a; + } +} diff --git a/orx-noise/src/shaders/glsl/noise/value.frag b/orx-noise/src/shaders/glsl/noise/value.frag new file mode 100644 index 00000000..990b27c9 --- /dev/null +++ b/orx-noise/src/shaders/glsl/noise/value.frag @@ -0,0 +1,52 @@ +// based on https://www.shadertoy.com/view/4dS3Wd + +// uniforms +uniform vec4 gain; +uniform vec4 bias; +uniform vec2 seed; + +uniform vec2 scale; +uniform vec2 lacunarity; +uniform vec4 decay; +uniform int octaves; +uniform bool premultipliedAlpha; + +// varyings +in vec2 v_texCoord0; + +// outputs +out vec4 o_output; + +float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } + +float noise(vec2 x) { + vec2 i = floor(x); + vec2 f = fract(x); + + float a = hash(i); + float b = hash(i + vec2(1.0, 0.0)); + float c = hash(i + vec2(0.0, 1.0)); + float d = hash(i + vec2(1.0, 1.0)); + + vec2 u = f * f * (3.0 - 2.0 * f); + return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; +} + +void main() { + vec4 result = vec4(0.0); + vec4 _gain = gain; + + vec2 shift = vec2(100); + mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50)); + vec2 x = ((v_texCoord0+seed) * scale); + for (int o = 0; o < octaves; ++o) { + result += noise(x) * _gain; + x = rot * x * lacunarity + shift; + _gain *= decay; + } + o_output = result + bias; + + if (premultipliedAlpha) { + o_output.rgb *= o_output.a; + } +} \ No newline at end of file diff --git a/orx-noise/src/shaders/glsl/noise/worley.frag b/orx-noise/src/shaders/glsl/noise/worley.frag new file mode 100644 index 00000000..743211d3 --- /dev/null +++ b/orx-noise/src/shaders/glsl/noise/worley.frag @@ -0,0 +1,72 @@ +// uniforms +uniform float scale; +uniform vec2 offset; +uniform bool premultipliedAlpha; + +// varyings +in vec2 v_texCoord0; + +// outputs +out vec4 o_output; + + +vec3 permute(vec3 x) { + return mod((34.0 * x + 1.0) * x, 289.0); +} + +vec3 dist(vec3 x, vec3 y, bool manhattanDistance) { + return manhattanDistance ? abs(x) + abs(y) : (x * x + y * y); +} + +vec2 worley(vec2 P, float jitter, bool manhattanDistance) { + float K= 0.142857142857; // 1/7 + float Ko= 0.428571428571 ;// 3/7 + vec2 Pi = mod(floor(P), 289.0); + vec2 Pf = fract(P); + vec3 oi = vec3(-1.0, 0.0, 1.0); + vec3 of = vec3(-0.5, 0.5, 1.5); + vec3 px = permute(Pi.x + oi); + vec3 p = permute(px.x + Pi.y + oi); // p11, p12, p13 + vec3 ox = fract(p*K) - Ko; + vec3 oy = mod(floor(p*K),7.0)*K - Ko; + vec3 dx = Pf.x + 0.5 + jitter*ox; + vec3 dy = Pf.y - of + jitter*oy; + vec3 d1 = dist(dx,dy, manhattanDistance); // d11, d12 and d13, squared + p = permute(px.y + Pi.y + oi); // p21, p22, p23 + ox = fract(p*K) - Ko; + oy = mod(floor(p*K),7.0)*K - Ko; + dx = Pf.x - 0.5 + jitter*ox; + dy = Pf.y - of + jitter*oy; + vec3 d2 = dist(dx,dy, manhattanDistance); // d21, d22 and d23, squared + p = permute(px.z + Pi.y + oi); // p31, p32, p33 + ox = fract(p*K) - Ko; + oy = mod(floor(p*K),7.0)*K - Ko; + dx = Pf.x - 1.5 + jitter*ox; + dy = Pf.y - of + jitter*oy; + vec3 d3 = dist(dx,dy, manhattanDistance); // d31, d32 and d33, squared + // Sort out the two smallest distances (F1, F2) + vec3 d1a = min(d1, d2); + d2 = max(d1, d2); // Swap to keep candidates for F2 + d2 = min(d2, d3); // neither F1 nor F2 are now in d3 + d1 = min(d1a, d2); // F1 is now in d1 + d2 = max(d1a, d2); // Swap to keep candidates for F2 + d1.xy = (d1.x < d1.y) ? d1.xy : d1.yx; // Swap if smaller + d1.xz = (d1.x < d1.z) ? d1.xz : d1.zx; // F1 is in d1.x + d1.yz = min(d1.yz, d2.yz); // F2 is now not in d2.yz + d1.y = min(d1.y, d1.z); // nor in d1.z + d1.y = min(d1.y, d2.x); // F2 is in d1.y, we're done. + return sqrt(d1.xy); +} + + +void main() { + vec2 F = worley(v_texCoord0 * scale + offset, 1.0, false); + float F1 = F.x; + float F2 = F.y; + + o_output = vec4(vec3(F2 - F1), 1.0); + + if (premultipliedAlpha) { + o_output.rgb *= o_output.a; + } +} \ No newline at end of file