diff --git a/orx-fx/src/jvmDemo/kotlin/DemoApproximateGaussianBlur01.kt b/orx-fx/src/jvmDemo/kotlin/DemoApproximateGaussianBlur01.kt index bac12fef..7e8258a2 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoApproximateGaussianBlur01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoApproximateGaussianBlur01.kt @@ -4,6 +4,14 @@ import org.openrndr.draw.loadImage import org.openrndr.extra.fx.blur.ApproximateGaussianBlur import org.openrndr.extra.imageFit.imageFit +/** + * Demonstrates how to use the [ApproximateGaussianBlur] effect to blur + * a `colorBuffer`, in this case, an image loaded from disk. + * + * Notice the use of `createEquivalent()`, which creates a new `colorBuffer` + * with the same size and properties as a source `colorBuffer`. + * + */ fun main() = application { configure { width = 720 diff --git a/orx-fx/src/jvmDemo/kotlin/DemoBlur01.kt b/orx-fx/src/jvmDemo/kotlin/DemoBlur01.kt index 41f925ff..355812cc 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoBlur01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoBlur01.kt @@ -5,6 +5,14 @@ import org.openrndr.extra.fx.blur.* import org.openrndr.math.Polar import kotlin.math.sin +/** + * Demonstrates 9 different blur effects. + * The program draws two moving circles into a [RenderTarget], + * then applies various blurs drawing them in 3 columns and 3 rows. + * + * Each type of blur has different parameters. + * Not all parameters are demonstrated. + */ fun main() = application { program { // In this buffer we will draw some simple shapes @@ -21,7 +29,8 @@ fun main() = application { GaussianBloom(), FrameBlur(), ZoomBlur(), - LaserBlur() + LaserBlur(), + LineBlur() ) // On this buffer we will draw the dry buffer with an effect applied @@ -32,15 +41,17 @@ fun main() = application { extend { // Draw two moving circles drawer.isolatedWithTarget(dry) { + ortho(dry) + clear(ColorRGBa.BLACK) fill = null stroke = ColorRGBa.PINK - strokeWeight = 25.0 + strokeWeight = 20.0 circle( bounds.center + Polar(seconds * 50.0, 100.0).cartesian, - 200.0 + 50.0 * sin(seconds * 2.0) + 100.0 + 50.0 * sin(seconds * 2.0) ) fill = ColorRGBa.PINK @@ -48,7 +59,7 @@ fun main() = application { circle( bounds.center + Polar(seconds * 50.0 + 60, 100.0).cartesian, - 100.0 + 20.0 * sin(seconds * 2.0 + 1) + 70.0 + 20.0 * sin(seconds * 2.0 + 1) ) } @@ -100,6 +111,10 @@ fun main() = application { blur.radius = 0.5 } + is LineBlur -> { + blur.blurAngle = seconds * 30.0 + blur.spread = 8.0 + } } // Apply the effect on `dry` writing the result to `wet` diff --git a/orx-fx/src/jvmDemo/kotlin/DemoCannyEdgeDetector01.kt b/orx-fx/src/jvmDemo/kotlin/DemoCannyEdgeDetector01.kt index 58dc548f..59ffe983 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoCannyEdgeDetector01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoCannyEdgeDetector01.kt @@ -3,6 +3,10 @@ import org.openrndr.draw.createEquivalent import org.openrndr.draw.loadImage import org.openrndr.extra.fx.edges.CannyEdgeDetector +/** + * Demonstrates the [CannyEdgeDetector] effect applied to a loaded + * color photograph. + */ fun main() = application { program { val image = loadImage("demo-data/images/image-001.png") diff --git a/orx-fx/src/jvmDemo/kotlin/DemoColorDuotone01.kt b/orx-fx/src/jvmDemo/kotlin/DemoColorDuotone01.kt index 67401c1c..f2739cab 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoColorDuotone01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoColorDuotone01.kt @@ -3,6 +3,13 @@ import org.openrndr.draw.createEquivalent import org.openrndr.draw.loadImage import org.openrndr.extra.fx.color.Duotone +/** + * This demo shows how to use the [Duotone] filter, + * toggling the `labInterpolation` parameter every second on and off. + * + * The `foregroundColor` and `backgroundColor` parameters are + * left to their defaults. + */ fun main() = application { program { diff --git a/orx-fx/src/jvmDemo/kotlin/DemoColorDuotoneGradient01.kt b/orx-fx/src/jvmDemo/kotlin/DemoColorDuotoneGradient01.kt index 1cbffdac..fd0a2fd5 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoColorDuotoneGradient01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoColorDuotoneGradient01.kt @@ -4,6 +4,15 @@ import org.openrndr.draw.createEquivalent import org.openrndr.draw.loadImage import org.openrndr.extra.fx.color.DuotoneGradient +/** + * The [DuotoneGradient] effect combines the Duotone effect + * and a linear gradient: two duotone colors are applied on + * one part of the image, and those colors are interpolated + * to two other colors, applied in a different part of the image. + * + * The `rotation` parameter lets us specify in which direction + * the interpolation happens (vertical, horizontal, or something else). + */ fun main() = application { program { val image = loadImage("demo-data/images/image-001.png") diff --git a/orx-fx/src/jvmDemo/kotlin/DemoColorPosterize01.kt b/orx-fx/src/jvmDemo/kotlin/DemoColorPosterize01.kt index 01365050..88e6f794 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoColorPosterize01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoColorPosterize01.kt @@ -3,6 +3,10 @@ import org.openrndr.draw.createEquivalent import org.openrndr.draw.loadImage import org.openrndr.extra.fx.color.Posterize +/** + * Demonstration of the [Posterize] effect to reduce the number of colors + * present in an image. + */ fun main() = application { program { val image = loadImage("demo-data/images/image-001.png") diff --git a/orx-fx/src/jvmDemo/kotlin/DemoColormapGrayscale.kt b/orx-fx/src/jvmDemo/kotlin/DemoColormapGrayscale.kt index 44c52d1f..06dda92c 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoColormapGrayscale.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoColormapGrayscale.kt @@ -5,6 +5,12 @@ import org.openrndr.draw.loadImage import org.openrndr.extra.fx.colormap.GrayscaleColormap import kotlin.math.sin +/** + * The [GrayscaleColormap] uses the red channel of a colorBuffer + * to produce a gray scale image. The `curve` parameter is used as + * an exponent to bias the result up or down. 1.0 produces a linear + * transformation. + */ fun main() = application { program { val colormap = GrayscaleColormap() diff --git a/orx-fx/src/jvmDemo/kotlin/DemoColormapSpectralZucconi.kt b/orx-fx/src/jvmDemo/kotlin/DemoColormapSpectralZucconi.kt index ea26df55..61a64c9d 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoColormapSpectralZucconi.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoColormapSpectralZucconi.kt @@ -5,6 +5,13 @@ import org.openrndr.draw.loadImage import org.openrndr.extra.fx.colormap.SpectralZucconiColormap import kotlin.math.sin +/** + * Demonstrates the [SpectralZucconiColormap], which + * maps values of the RED color channel to the natural light dispersion + * spectrum as described by Alan Zucconi in his + * [Improving the Rainbow](https://www.alanzucconi.com/2017/07/15/improving-the-rainbow/) + * article. + */ fun main() = application { program { val colormap = SpectralZucconiColormap() diff --git a/orx-fx/src/jvmDemo/kotlin/DemoColormapTurbo.kt b/orx-fx/src/jvmDemo/kotlin/DemoColormapTurbo.kt index 66d16501..fcdb6930 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoColormapTurbo.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoColormapTurbo.kt @@ -5,6 +5,12 @@ import org.openrndr.draw.loadImage import org.openrndr.extra.fx.colormap.TurboColormap import kotlin.math.sin +/** + * Demonstrates the use of the [TurboColormap] effect, which + * maps values of the RED color channel to Turbo Colormap according to + * [Turbo, An Improved Rainbow Colormap for Visualization](https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html) + * by Google. + */ fun main() = application { program { val colormap = TurboColormap() diff --git a/orx-fx/src/jvmDemo/kotlin/DemoCompositeFilter01.kt b/orx-fx/src/jvmDemo/kotlin/DemoCompositeFilter01.kt index 0ec3a545..547ea766 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoCompositeFilter01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoCompositeFilter01.kt @@ -10,49 +10,69 @@ import org.openrndr.extra.fx.grain.FilmGrain import org.openrndr.extra.noise.* import org.openrndr.math.smoothstep import kotlin.math.cos +import kotlin.math.sin +/** + * Advanced demonstration of composite filters, created by chaining + * several filters together using the `.then()` operator. + * + * The demo applies a [FilmGrain] effect and a [DirectionalBlur] effect twice + * with different parameters. + * + * The [DirectionalBlur] requires a color buffer to define the displacement + * directions. In this program, the direction color buffer is populated by writing + * into its `shadow` property pixel by pixel. + * + * Notice the use of `frameCount` and `seconds` to animate the effects. + * + * The composite effect is installed as a post-processing effect + * using `extend(Post())`, so anything drawn in following `extend` + * blocks is affected by it. + */ fun main() = application { program { + // -- create a color buffer and fill it with random direction vectors + val direction = colorBuffer(width, height, type = ColorType.FLOAT32) + val s = direction.shadow + val n = simplex2D.bipolar().fbm().scaleShiftInput(0.01, 0.0, 0.01, 0.0).withVector2Output() + val ng = simplex2D.unipolar().scaleShiftInput(0.005, 0.0, 0.005, 0.0) + for (y in 0 until height) { + for (x in 0 until width) { + val nv = n(2320, x.toDouble(), y.toDouble()) * smoothstep( + 0.45, + 0.55, + ng(1032, x.toDouble(), y.toDouble()) + ) + s[x, y] = ColorRGBa(nv.x, nv.y, 0.0, 1.0) + } + } + s.upload() + + val directional = DirectionalBlur() + + // -- create a bidirectional composite filter by using a directional filter twice + val bidirectional = directional.then(directional) { + firstParameters { + window = 50 + spread = 1.5 + sin(seconds) + perpendicular = false + } + secondParameters { + window = 3 + spread = 1.5 + cos(seconds) + perpendicular = true + } + } + + val grain = FilmGrain() + grain.grainStrength = 1.0 + + // -- create a grain-blur composite filter + val grainBlur = bidirectional.then(grain) + extend(Post()) { - // -- create a color buffer and fill it with random direction vectors - val direction = colorBuffer(width, height, type = ColorType.FLOAT32) - val s = direction.shadow - val n = simplex2D.bipolar().fbm().scaleShiftInput(0.01, 0.0, 0.01, 0.0).withVector2Output() - val ng = simplex2D.unipolar().scaleShiftInput(0.005, 0.0, 0.005, 0.0) - for (y in 0 until height) { - for (x in 0 until width) { - val a = smoothstep(0.4, 0.6, cos((x + y) * 0.01) * 0.5 + 0.5) - val nv = n(2320, x.toDouble(), y.toDouble()) * smoothstep( - 0.45, - 0.55, - ng(1032, x.toDouble(), y.toDouble()) - ) - s[x, y] = ColorRGBa(nv.x, nv.y, 0.0, 1.0) - } - } - s.upload() - - val directional = DirectionalBlur() - - // -- create a bidirectional composite filter by using a directional filter twice - val bidirectional = directional.then(directional) { - firstParameters { - window = 50 - perpendicular = false - } - secondParameters { - window = 3 - perpendicular = true - } - } - - val grain = FilmGrain() - grain.grainStrength = 1.0 - - // -- create a grain-blur composite filter - val grainBlur = grain.then(bidirectional) - post { input, output -> + grain.time = frameCount * 1.0 grainBlur.apply(arrayOf(input, direction), output) } } diff --git a/orx-fx/src/jvmDemo/kotlin/DemoContour01.kt b/orx-fx/src/jvmDemo/kotlin/DemoContour01.kt index a653ef8c..ee81f248 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoContour01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoContour01.kt @@ -1,8 +1,3 @@ -/** - * Demonstrate the Contour filter - * @author Edwin Jakobs - */ - import org.openrndr.application import org.openrndr.color.ColorRGBa import org.openrndr.draw.createEquivalent @@ -11,6 +6,20 @@ import org.openrndr.extra.fx.edges.Contour import org.openrndr.extra.imageFit.imageFit import org.openrndr.extra.shapes.primitives.grid +/** + * Demonstrates the [Contour] filter. + * @author Edwin Jakobs + * + * This demo creates a grid of 2x2 to draw a loaded image four times, + * each using the [Contour] effect with different parameters. + * + * `actions` is a variable containing a list of 4 functions. + * Each of these functions sets the effect parameters to different values. + * + * The 4 grid cells and the 4 actions are used in pairs: + * first the action is called to set the effect parameters, the + * effect is applied, and the result is drawn in a cell. + */ fun main() = application { configure { width = 720 @@ -19,33 +28,32 @@ fun main() = application { program { val image = loadImage("demo-data/images/image-001.png") val contour = Contour() - contour.levels = 4.0 contour.window = 1 - contour.outputBands = true contour.contourColor = ColorRGBa.PINK contour.backgroundOpacity = 0.0 val edges = image.createEquivalent() + + val cells = drawer.bounds.grid(2, 2).flatten() + val actions = listOf( + { + contour.outputBands = true + contour.levels = 2.0 + }, + { + contour.outputBands = false + contour.levels = 2.0 + }, + { + contour.outputBands = false + contour.levels = 8.0 + }, + { + contour.outputBands = true + contour.levels = 8.0 + }, + ) extend { - val cells = drawer.bounds.grid(2, 2).flatten() - val actions = listOf( - { - contour.outputBands = true - contour.levels = 2.0 - }, - { - contour.outputBands = false - contour.levels = 2.0 - }, - { - contour.outputBands = false - contour.levels = 8.0 - }, - { - contour.outputBands = true - contour.levels = 8.0 - }, - ) for ((cell, action) in cells zip actions) { action() contour.apply(image, edges) diff --git a/orx-fx/src/jvmDemo/kotlin/DemoDistortLenses01.kt b/orx-fx/src/jvmDemo/kotlin/DemoDistortLenses01.kt index 0d39a026..8b5fa656 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoDistortLenses01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoDistortLenses01.kt @@ -3,6 +3,12 @@ import org.openrndr.draw.createEquivalent import org.openrndr.draw.loadImage import org.openrndr.extra.fx.distort.Lenses +/** + * Demonstrates the [Lenses] effect, which by default subdivides a color buffer + * in 8 columns and 6 rows, and displaces the source texture inside each rectangle. + * Try experimenting with some of the other parameters, like `distort`. + * You can even animate them. + */ fun main() = application { configure { width = 640 @@ -14,7 +20,7 @@ fun main() = application { val lenses = Lenses() val edges = image.createEquivalent() extend { - lenses.rotation = 0.0 + lenses.rotation = 30.0 lenses.scale = 1.5 lenses.apply(image, edges) diff --git a/orx-fx/src/jvmDemo/kotlin/DemoDitherLumaHalftone01.kt b/orx-fx/src/jvmDemo/kotlin/DemoDitherLumaHalftone01.kt index ecb8c537..b1ea9558 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoDitherLumaHalftone01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoDitherLumaHalftone01.kt @@ -3,6 +3,12 @@ import org.openrndr.draw.createEquivalent import org.openrndr.draw.loadImage import org.openrndr.extra.fx.dither.LumaHalftone +/** + * Demonstrates the [LumaHalftone] effect and moste of its parameters. + * The `invert` parameter toggles between true and false once per second. + * The `phase0` and `phase1` parameters depend on `seconds`, which makes + * the pattern wobble slowly. + */ fun main() = application { program { val image = loadImage("demo-data/images/image-001.png") diff --git a/orx-fx/src/jvmDemo/kotlin/DemoFluidDistort01.kt b/orx-fx/src/jvmDemo/kotlin/DemoFluidDistort01.kt index bd64fee2..f30c3bb4 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoFluidDistort01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoFluidDistort01.kt @@ -5,6 +5,10 @@ import org.openrndr.extensions.SingleScreenshot import org.openrndr.extra.fx.distort.FluidDistort import org.openrndr.extra.fx.patterns.Checkers +/** + * Demonstrates [FluidDistort], a fluid simulation real time effect. + * All pixels are slowly displaced in a turbulent manner as if they were a gas or a liquid. + */ fun main() = application { program { val fd = FluidDistort() diff --git a/orx-fx/src/jvmDemo/kotlin/DemoPost01.kt b/orx-fx/src/jvmDemo/kotlin/DemoPost01.kt index 7b4bc756..0de32bb4 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoPost01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoPost01.kt @@ -4,6 +4,15 @@ import org.openrndr.extra.fx.blend.Add import org.openrndr.extra.fx.blur.ApproximateGaussianBlur import kotlin.math.cos +/** + * Demonstrates how to create an `extend` block to apply a post-processing effect. + * The effect is an [ApproximateGaussianBlur] and its `sigma` parameter + * is animated. The Blur effect is combined with whatever the user draws + * in the regular `extend` block using the `Add` filter, resulting in + * an additive composition. + * + * This demo also shows how to make a program window resizable. + */ fun main() = application { configure { windowResizable = true diff --git a/orx-fx/src/jvmDemo/kotlin/DemoSpectralBlend01.kt b/orx-fx/src/jvmDemo/kotlin/DemoSpectralBlend01.kt index fff8f54f..d343107b 100644 --- a/orx-fx/src/jvmDemo/kotlin/DemoSpectralBlend01.kt +++ b/orx-fx/src/jvmDemo/kotlin/DemoSpectralBlend01.kt @@ -8,6 +8,20 @@ import org.openrndr.extra.fx.patterns.Checkers import org.openrndr.math.Vector2 import kotlin.math.sin +/** + * Demonstration of how to use the [BlendSpectral] filter to combine two images, using + * this pigment-simulation color mixing approach. + * + * The program: + * - generates two images + * - blurs one of them + * - creates and draws a checkers-pattern as the background + * - mixes and draws both images + * + * The `fill` factor, which controls how the top and the bottom colors are mixed, is animated. + * + * The `clip` parameter is also animated and toggles every 6 seconds. + */ fun main() = application { configure { width = 800 @@ -35,7 +49,7 @@ fun main() = application { extend { drawer.image(checked) blendSpectral.fill = sin(seconds) * 0.5 + 0.5 - blendSpectral.clip = seconds.mod(4.0) > 2.0 + blendSpectral.clip = seconds.mod(12.0) > 6.0 blendSpectral.apply(a, b, mixed) drawer.image(mixed) }