Add descriptions to demos

This commit is contained in:
Abe Pazos
2025-11-22 19:08:30 +01:00
parent 72368deb85
commit 522627ca51
45 changed files with 608 additions and 89 deletions

View File

@@ -1,8 +1,5 @@
package colorRange
// Comparison of color lists generated by interpolating from
// PINK to BLUE in different color models
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.palettes.rangeTo
@@ -11,6 +8,10 @@ import org.openrndr.math.Vector2
import org.openrndr.math.map
import org.openrndr.shape.Rectangle
/**
* Comparison of color lists generated by interpolating from
* `PINK` to `BLUE` in six different color spaces.
*/
fun main() = application {
configure {
width = 720

View File

@@ -1,12 +1,19 @@
package colorRange
// Create a colorSequence with multiple color models
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.palettes.colorSequence
import org.openrndr.extra.color.spaces.toHSLUVa
/**
* Demonstrates how to create a `ColorSequence` containing three colors, one of them in the HSLUV color space.
*
* Each color in the sequence is assigned a normalized position: in this program, one at the start (0.0),
* one in the middle (0.5) and one at the end (1.0).
*
* The `ColorSpace.blend()` method is used to get a list with 18 interpolated `ColorRGBa` colors,
* then those colors are drawn as vertical rectangles covering the whole window.
*/
fun main() = application {
configure {
width = 720
@@ -14,9 +21,11 @@ fun main() = application {
}
program {
extend {
val cs = colorSequence(0.0 to ColorRGBa.PINK,
val cs = colorSequence(
0.0 to ColorRGBa.PINK,
0.5 to ColorRGBa.BLUE,
1.0 to ColorRGBa.PINK.toHSLUVa()) // <-- note this one is in hsluv
1.0 to ColorRGBa.PINK.toHSLUVa() // <-- note this color is in HSLUV
)
for (c in cs blend (width / 40)) {
drawer.fill = c

View File

@@ -6,15 +6,16 @@ import org.openrndr.draw.loadFont
import org.openrndr.extra.color.palettes.rangeTo
import org.openrndr.extra.color.spaces.*
/**
* This program creates color interpolations from `ColorRGBa.BLUE` to
* `ColorRGBa.PINK` in 25 steps in multiple color spaces.
*
* The window height is adjusted based on the number of interpolations to show.
*
* The resulting gradients differ in saturation and brightness and apparently include more
* `BLUE` or more `PINK` depending on the chosen color space.
*/
fun main() = application {
configure {
width = 720
height = 30 + 50 * 11 // row count
}
program {
extend {
drawer.clear(ColorRGBa.WHITE)
val colorA = ColorRGBa.BLUE
val colorB = ColorRGBa.PINK
@@ -34,8 +35,14 @@ fun main() = application {
"XSLUV" to (colorA.toXSLUVa()..colorB.toXSLUVa() blend stepCount),
)
configure {
width = 720
height = 30 + 50 * allSteps.size
}
program {
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.stroke = null
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.translate(20.0, 20.0)
for ((label, steps) in allSteps) {

View File

@@ -14,6 +14,20 @@ import org.openrndr.extra.color.spaces.toXSLUVa
import org.openrndr.extra.meshgenerators.sphereMesh
import org.openrndr.math.Vector3
/**
* A visualization of color interpolations inside a 3D RGB cube with an interactive 3D `Orbital` camera.
*
* The hues of the source and target colors are animated over time.
*
* The color interpolations are shown simultaneously in nine different color spaces, revealing how in
* each case they share common starting and ending points in 3D, but have unique paths going from
* start to end.
*
* By rotating the cube 90 degrees towards the left and slightly zooming out, one can appreciate how
* one of the points moves along the edges of the cube, while the other moves on the edges of a
* smaller, invisible cube.
*
*/
fun main() = application {
configure {
width = 720
@@ -44,9 +58,6 @@ fun main() = application {
"XSLUV" to (colorA.toXSLUVa()..colorB.toXSLUVa() blend stepCount),
)
drawer.stroke = null
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
for ((_, steps) in allSteps) {
for (i in steps.indices) {
val srgb = steps[i].toSRGB().clip()

View File

@@ -5,6 +5,14 @@ import org.openrndr.extra.color.colormaps.spectralZucconi6
import org.openrndr.extra.noise.fastFloor
import kotlin.math.sin
/**
* This program demonstrates the `spectralZucconi6()` function, which
* takes a normalized value and returns a `ColorRGBa` using the
* accurate spectral colormap developed by Alan Zucconi.
*
* It draws a varying number of vertical bands (between 16 and 48)
* filled with various hues.
*/
fun main() = application {
configure {
width = 720
@@ -14,12 +22,13 @@ fun main() = application {
extend {
drawer.stroke = null
val stripeCount = 32 + (sin(seconds) * 16.0).fastFloor()
val bandWidth = width / stripeCount.toDouble()
repeat(stripeCount) { i ->
drawer.fill = spectralZucconi6(i / stripeCount.toDouble())
drawer.rectangle(
x = i * width / stripeCount.toDouble(),
x = i * bandWidth,
y = 0.0,
width = width / stripeCount.toDouble(),
width = bandWidth,
height = height.toDouble(),
)
}

View File

@@ -5,6 +5,15 @@ import org.openrndr.draw.shadeStyle
import org.openrndr.extra.color.colormaps.ColormapPhraseBook
import org.openrndr.extra.shaderphrases.preprocess
/**
* This program demonstrates how to use the shader-based version of
* the `spectral_zucconi6()` function, which
* takes a normalized value and returns an `rgb` color using the
* accurate spectral colormap developed by Alan Zucconi.
*
* It shades a full-window rectangle using its normalized `x` coordinate
* in a `ShadeStyle` to choose pixel colors.
*/
fun main() = application {
configure {
width = 720

View File

@@ -8,6 +8,13 @@ import org.openrndr.extra.color.colormaps.spectralZucconi6
import org.openrndr.extra.shaderphrases.preprocess
import org.openrndr.math.Vector2
/**
* This demo uses the shader based `spectral_zucconi6()` function to fill the background,
* then visualizes the red, green and blue components of the colors used in the background
* as red, green and blue line strips.
*
* The Vector2 points for the line strips are calculated only once when the program starts.
*/
fun main() = application {
configure {
width = 720
@@ -20,14 +27,14 @@ fun main() = application {
fragmentTransform = "x_fill.rgb = spectral_zucconi6(c_boundsPosition.x);"
}
// Function that expects as an argument a function to convert a ColorRGBa into a Double,
// and returns a list of Vector2 coordinates.
fun getColormapPoints(
block: ColorRGBa.() -> Double
) = List(width) { x ->
Vector2(
x.toDouble(),
height.toDouble()
- block(spectralZucconi6(x / width.toDouble()))
* height.toDouble()
(1.0 - block(spectralZucconi6(x / width.toDouble()))) * height
)
}
@@ -39,11 +46,13 @@ fun main() = application {
shadeStyle = backgroundStyle
rectangle(bounds)
shadeStyle = null
strokeWeight = 1.0
stroke = ColorRGBa.RED
lineStrip(redPoints)
stroke = ColorRGBa.GREEN
lineStrip(greenPoints)
stroke = ColorRGBa.BLUE
lineStrip(bluePoints)
}

View File

@@ -5,6 +5,15 @@ import org.openrndr.extra.color.colormaps.turboColormap
import org.openrndr.extra.noise.fastFloor
import kotlin.math.sin
/**
* This program demonstrates the `turboColormap()` function, which
* takes a normalized value and returns a `ColorRGBa` using the
* Turbo colormap developed by Google.
*
* It draws a varying number of vertical bands (between 16 and 48)
* filled with various hues.
*/
fun main() = application {
configure {
width = 720

View File

@@ -5,6 +5,15 @@ import org.openrndr.draw.shadeStyle
import org.openrndr.extra.color.colormaps.ColormapPhraseBook
import org.openrndr.extra.shaderphrases.preprocess
/**
* This program demonstrates how to use the shader-based version of
* the `turbo_colormap()` function, which
* takes a normalized value and returns an `rgb` color using the
* Turbo colormap developed by Google.
*
* It shades a full-window rectangle using its normalized `x` coordinate
* in a `ShadeStyle` to choose pixel colors.
*/
fun main() = application {
configure {
width = 720

View File

@@ -8,6 +8,13 @@ import org.openrndr.extra.color.colormaps.turboColormap
import org.openrndr.extra.shaderphrases.preprocess
import org.openrndr.math.Vector2
/**
* This demo uses the shader based `turbo_colormap()` function to fill the background,
* then visualizes the red, green and blue components of the colors used in the background
* as red, green and blue line strips.
*
* The Vector2 points for the line strips are calculated only once when the program starts.
*/
fun main() = application {
configure {
width = 720
@@ -23,10 +30,8 @@ fun main() = application {
block: ColorRGBa.() -> Double
) = List(width) { x ->
Vector2(
x = x.toDouble(),
y = height.toDouble()
- block(turboColormap(x / width.toDouble()))
* height.toDouble()
x.toDouble(),
(1.0 - block(turboColormap(x / width.toDouble()))) * height
)
}
val redPoints = getColormapPoints { r }
@@ -37,11 +42,13 @@ fun main() = application {
shadeStyle = backgroundStyle
rectangle(bounds)
shadeStyle = null
strokeWeight = 1.0
stroke = ColorRGBa.RED
lineStrip(redPoints)
stroke = ColorRGBa.GREEN
lineStrip(greenPoints)
stroke = ColorRGBa.BLUE
lineStrip(bluePoints)
}

View File

@@ -12,6 +12,18 @@ import org.openrndr.draw.loadImage
import kotlin.math.cos
import kotlin.math.sin
/**
* Demonstrates how to convert a PNG image into `ShapeContour`s using BoofCV.
*
* Two helper methods help convert data types between BoofCV and OPENRNDR.
*
* The `ColorBuffer.toGrayF32()` method converts an OPENRNDR `ColorBuffer` to `GrayF32` format,
* required by BoofCV.
*
* The `.toShapeContours()` converts BoofCV contours to OPENRNDR `ShapeContour` instances.
*
* The resulting contours are animated zooming in and out while their colors change slowly.
*/
fun main() = application {
program {
// Load an image, convert to BoofCV format using orx-boofcv

View File

@@ -2,19 +2,31 @@ import org.openrndr.application
import org.openrndr.boofcv.binding.resizeBy
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.loadImage
import org.openrndr.math.Vector2
/**
* Demonstrates how to scale down images using the `resizeBy` BoofCV-based
* method.
*/
fun main() = application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png")
val scaled = input.resizeBy(0.5)
val scaled2 = input.resizeBy(0.25, convertToGray = true)
val scaled3 = input.resizeBy(0.1)
println("${input.width} x ${input.height}")
println("${scaled.width} x ${scaled.height}")
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
// Display the loaded image to the right of `scaled` matching its size
drawer.image(input, scaled.bounds.movedBy(Vector2.UNIT_X * scaled.bounds.width))
// Display actually scaled down versions of the loaded image
drawer.image(scaled)
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)

View File

@@ -3,17 +3,29 @@ import org.openrndr.boofcv.binding.resizeTo
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.loadImage
/**
* Demonstrates how to scale down images using the `resizeTo` BoofCV-based
* method.
*
* If only the `newWidth` or the `newHeight` arguments are specified,
* the resizing happens maintaining the original aspect ratio.
*/
fun main() = application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png")
val scaled = input.resizeTo(input.width / 3)
val scaled2 = input.resizeTo(newHeight = input.height / 4, convertToGray = true)
val scaled3 = input.resizeTo(input.width / 5, input.height / 5)
println("${input.width} x ${input.height}")
println("${scaled.width} x ${scaled.height}")
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
// Display actually scaled down versions of the loaded image
drawer.image(scaled)
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)

View File

@@ -17,6 +17,18 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
import org.openrndr.shape.ShapeContour
/**
* When converting a `ColorBuffer` to `ShapeContour` instances using
* `BoofCV`, simple shapes can have hundreds of segments and vertices.
*
* This demo shows how to use the `simplify()` method to greatly
* reduce the number of vertices.
*
* Then it uses the simplified vertex lists to create smooth curves
* (using `CatmullRomChain2`) and polygonal curves (using `ShapeContour.fromPoints`).
*
* Study the console to learn about the number of segments before and after simplification.
*/
fun main() = application {
program {
// Create a buffer where to draw something for boofcv
@@ -41,6 +53,7 @@ fun main() = application {
rectangle(0.0, -200.0, 60.0, 60.0)
circle(0.0, 190.0, 60.0)
}
// Convert the bitmap buffer into ShapeContours
val vectorized = imageToContours(rt.colorBuffer(0))
@@ -73,8 +86,11 @@ fun main() = application {
extend {
drawer.run {
fill = null // ColorRGBa.PINK.opacify(0.15)
stroke = ColorRGBa.PINK.opacify(0.7)
contours(polygonal)
stroke = ColorRGBa.GREEN.opacify(0.7)
contours(smooth)
}
}

View File

@@ -7,7 +7,10 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
/**
* A simple demonstration of a GUI for drawing some circles
* Demonstrates how to customize the appearance of the GUI by using
* `GUIAppearance()`.
*
* In this demo, we make the GUI wider (400 pixels) and translucent.
*/
fun main() = application {
program {

View File

@@ -6,7 +6,7 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
/**
* A simple demonstration of a GUI for drawing some circles
* Demonstrates how to hide the GUI when the mouse pointer is outside of it.
*/
fun main() = application {
program {
@@ -29,7 +29,7 @@ fun main() = application {
gui.add(settings)
extend(gui)
// note we can only change the visibility after the extend
// note we can only change the visibility after the `extend`
gui.visible = false
extend {

View File

@@ -6,7 +6,7 @@ import org.openrndr.window
import kotlin.system.exitProcess
/**
* Demonstration of multi window GUI in the manual way
* Demonstration of a multi window GUI in the manual way
*/
fun main() {
// skip this demo on CI

View File

@@ -4,7 +4,7 @@ import org.openrndr.extra.parameters.DoubleParameter
import kotlin.system.exitProcess
/**
* Demonstration of multi window GUI using WindowedGUI extension
* Demonstration of a multi window GUI using the `WindowedGUI` extension
*/
fun main() {
// skip this demo on CI

View File

@@ -5,7 +5,9 @@ import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.OptionParameter
/**
* A simple demonstration of a GUI with a drop down menu
* A simple demonstration of a GUI with a drop-down menu.
*
* The entries in the drop-down menu are taken from an `enum class`.
*/
enum class BackgroundColors {
@@ -15,6 +17,10 @@ enum class BackgroundColors {
}
fun main() = application {
configure {
width = 720
height = 360
}
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false

View File

@@ -0,0 +1,43 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.gui.GUI
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.OptionParameter
/**
* A simple demonstration of a GUI with a drop-down menu.
*
* The entries in the drop-down menu are taken from an `enum class`.
* The `enum class` entries contain both a name (used in the drop-down)
* and a `ColorRGBa` instance (used for rendering).
*/
enum class BackgroundColors2(val color: ColorRGBa) {
Pink(ColorRGBa.PINK),
Black(ColorRGBa.BLACK),
Yellow(ColorRGBa.YELLOW)
}
fun main() = application {
configure {
width = 720
height = 360
}
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
val settings = @Description("Settings") object {
@OptionParameter("Background color")
var option = BackgroundColors2.Pink
}
gui.add(settings)
extend(gui)
gui.onChange { name, value ->
println("$name: $value")
}
extend {
drawer.clear(settings.option.color)
}
}
}

View File

@@ -4,6 +4,18 @@ import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.PathParameter
import org.openrndr.extra.propertywatchers.watchingImagePath
/**
* Demonstrates how to include a button for loading images in a GUI, and how to display
* the loaded image.
*
* The program applies the `@PathParameter` annotation to a `String` variable, which gets
* rendered by the GUI as an image-picker button. Note the allowed file `extensions`.
*
* This mechanism only updates the `String` containing the path of an image file.
*
* The `watchingImagePath()` delegate property is used to automatically load an image
* when its `String` argument changes.
*/
fun main() = application {
program {
val gui = GUI()

View File

@@ -7,12 +7,18 @@ import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.IntParameter
/**
* Shows how to store and retrieve in-memory gui presets.
* Shows how to store and retrieve in-memory GUI presets,
* each containing two integer values and two colors.
*
* Keyboard controls:
* [Left Shift] + [0]..[9] => store current gui values to a preset
* [Left Shift] + [0]..[9] => store current GUI values to a preset
* [0]..[9] => recall a preset
*/
fun main() = application {
configure {
width = 720
height = 480
}
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
@@ -43,9 +49,9 @@ fun main() = application {
// Draw a pattern based on modulo
for (i in 0 until 100) {
if (i % settings.a == 0 || i % settings.b == 0) {
val x = (i % 10) * 64.0
val x = (i % 10) * 72.0
val y = (i / 10) * 48.0
drawer.rectangle(x, y, 64.0, 48.0)
drawer.rectangle(x, y, 72.0, 48.0)
}
}
}

View File

@@ -2,18 +2,29 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.gui.GUI
import org.openrndr.extra.gui.GUIAppearance
import org.openrndr.extra.parameters.*
import org.openrndr.math.Vector2
import org.openrndr.extra.parameters.ColorParameter
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.panel.elements.draw
/**
* A simple demonstration of a GUI for drawing some circles
* Demonstrates the `GUI.enableSideCanvas` feature.
*
* When set to true, the `GUI` provides a `canvas` property where one can draw.
* The size of this canvas is the window size minus the GUI size.
*
* That's why if we draw a circle at `drawer.width / 2.0` it is centered
* on the `canvas`, not on the window.
*
* This demo sets the window to resizable, so if you resize the window
* you should see tha the circle stays at the center of the canvas.
*
*/
fun main() = application {
configure {
width = 800
height = 800
width = 720
height = 720
windowResizable = true
}
@@ -23,17 +34,11 @@ fun main() = application {
gui.enableSideCanvas = true
val settings = @Description("Settings") object {
@DoubleParameter("radius", 0.0, 100.0)
@DoubleParameter("radius", 0.0, 200.0)
var radius = 50.0
@Vector2Parameter("position", 0.0, 1.0)
var position = Vector2(0.6, 0.5)
@ColorParameter("color")
var color = ColorRGBa.PINK
@DoubleListParameter("radii", 5.0, 30.0)
var radii = mutableListOf(5.0, 6.0, 8.0, 14.0, 20.0, 30.0)
}
gui.add(settings)
extend(gui)
@@ -42,7 +47,7 @@ fun main() = application {
val width = drawer.width
val height = drawer.height
drawer.fill = settings.color
drawer.circle(width/2.0, height/2.0, 100.0)
drawer.circle(width / 2.0, height / 2.0, settings.radius)
}
}
}

View File

@@ -6,11 +6,22 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
/**
* A simple demonstration of a GUI for drawing some circles
* Demonstrates how to create a simple GUI with 4 inputs:
* - A `ColorParameter` which creates a color picker.
* - A `DoubleParameter` to control the radius of a circle.
* - A `Vector2Parameter` to set the position of that circle.
* - A `DoubleListParameter` which sets the radii of six circles.
*
* The demo also shows how to use the variables controlled by the GUI
* inside the program, so changes to those variables affect
* the rendering in real time.
*/
fun main() = application {
configure {
width = 720
height = 450
}
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false

View File

@@ -4,6 +4,13 @@ import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.XYParameter
import org.openrndr.math.Vector2
/**
* Demonstrates the use of the `@XYParameter` annotation applied to a `Vector2` variable.
*
* This annotation creates an interactive XY control in a GUI that can be used to update
* a `Vector2` variable. In this demo it sets the position of a circle.
*
*/
fun main() = application {
configure {
width = 800

View File

@@ -6,7 +6,17 @@ import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.math.Vector4
/**
* Demonstrates how to use RabbitControl to create a web-based user interface for your program.
*
* A `settings` object is created using the same syntax used for `orx-gui`, including
* annotations for different variable types.
*
* The program then passes these `settings` to the `RabbitControlServer`. A QR-code is displayed
* to open the web user interface. A clickable URL is also displayed in the console.
*
* Once the UI is visible in a web browser we can use it to control the OPENRNDR program.
*/
fun main() = application {
configure {
width = 800

View File

@@ -4,6 +4,12 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.parameters.BooleanParameter
/**
* Demonstrates how the QR-code pointing at the Rabbit Control web-based user interface
* can be displayed and hidden manually.
*
* To display the QR-code overlay in this demo, hold down the HOME key in the keyboard.
*/
fun main() = application {
configure {
width = 800

View File

@@ -6,7 +6,15 @@ import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.math.Vector4
/**
* Starts the RabbitControlServer with a `Rabbithole` using the key 'orxtest'.
*
* `Rabbithole` allows you to access your exposed parameters from Internet
* connected computers that are not in the same network.
*
* To use it with this example use 'orxtest' as the tunnel-name in https://rabbithole.rabbitcontrol.cc
*
*/
fun main() = application {
configure {
width = 800
@@ -14,13 +22,6 @@ fun main() = application {
}
program {
/**
* Start RabbitControlServer with a Rabbithole with key 'orxtest'
* Please visit https://rabbithole.rabbitcontrol.cc for more information.
*
* Rabbithole allows you to access your exposed parameter from the internet.
* To use it with this example just use 'orxtest' as tunnel-name on the main page.
*/
val rabbit = RabbitControlServer(false, 10000, 8080, "wss://rabbithole.rabbitcontrol.cc/public/rcpserver/connect?key=orxtest")
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
val settings = object {

View File

@@ -8,6 +8,17 @@ import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.shape.Rectangle
/**
* Demonstrates how to create various types of 3D meshes:
* box, sphere, dodecahedron, cylinder, plane, cap and resolve.
*
* Two textures are used: one generative with gradients, and the second
* one is an image loaded from disk. The horizontal mouse position is used
* to select which of the two textures to use.
*
* The meshes are positioned in space using a 2D mesh, and displayed
* rotating on the X and Y axes at different speeds.
*/
fun main() = application {
configure {
width = 720

View File

@@ -9,6 +9,21 @@ import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.meshgenerators.boxMesh
import org.openrndr.math.Vector3
/**
* Demonstrates how to create a 3D mesh box by specifying its width, height and depth.
*
* The `box` is a `VertexBuffer` and contains texture coordinates which can be
* used to apply a texture to its faces.
*
* After creating the box, the program creates a texture with a gradient.
* In it, the red component increases along the x-axis and the green component
* along the y-axis.
*
* The scene is rendered with an interactive `Orbital` 3D camera.
*
* A shade style is used to apply the texture to the box.
*
*/
fun main() = application {
configure {
width = 720

View File

@@ -9,6 +9,17 @@ import org.openrndr.extra.meshgenerators.buildTriangleMesh
import org.openrndr.extra.meshgenerators.sphere
import org.openrndr.math.Vector3
/**
* Demonstrates how to use `buildTriangleMesh` to construct composite 3D meshes.
*
* A DSL allows specifying the color and transformations of each mesh, in this case,
* of a sphere and a box.
*
* An interactive 3D Orbital camera is defined, specifying the location of its `eye` and
* `lookAt` properties.
*
* A minimal shade style is used to simulate a uni-directional light pointing along the view Z axis.
*/
fun main() = application {
configure {
width = 720

View File

@@ -8,6 +8,9 @@ import org.openrndr.extra.meshgenerators.cylinder
import org.openrndr.extra.meshgenerators.hemisphere
import org.openrndr.math.Vector3
/**
* Demonstrates the creation of a 3D mesh composed of two hemispheres, a cylinder and 12 legs.
*/
fun main() = application {
configure {
width = 720

View File

@@ -6,6 +6,16 @@ import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.meshgenerators.*
import org.openrndr.math.Vector3
/**
* Demonstrates the creation of a 3D mesh composed of two hemispheres, a cylinder and 12 legs.
* Additionally, the body of the shape features 5 ridges on the sides
* of the cylinder.
*
* The code reveals DSL keywords under `buildTriangleMesh`
* affecting transformation matrices, for instance `isolated`, `translate` and `rotate`,
* and mesh generating keywords like
* `hemisphere`, `taperedCylinder` and `cylinder`.
*/
fun main() = application {
configure {
width = 720

View File

@@ -7,6 +7,11 @@ import org.openrndr.extra.meshgenerators.*
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
/**
* Demonstrates the use of `buildTriangleMesh` to create
* a composite 3D mesh and introduces a new mesh generating keyword:
* `cap`.
*/
fun main() = application {
configure {
width = 720

View File

@@ -11,6 +11,12 @@ import org.openrndr.extra.meshgenerators.twist
import org.openrndr.math.Vector3
import org.openrndr.shape.Circle
/**
* Demonstrates how to create a 3D grid of extruded shapes
* (short cylinders), then applies three 3D twists to the
* composition to deform it.
*
*/
fun main() = application {
configure {
width = 720

View File

@@ -9,8 +9,11 @@ import org.openrndr.extra.noise.simplex
import org.openrndr.math.Vector3
/**
* Generates a grid of grids of boxes.
* Interactive orbital camera.
* Generates a grid of grids of 3D boxes using `buildTriangleMesh` and
* renders them using an interactive orbital camera.
*
* The cubes ar colorized using a shade style that sets colors based
* on vertex positions in space, converting XYZ coordinates into RGB colors.
*
*/
fun main() = application {

View File

@@ -10,6 +10,15 @@ import org.openrndr.extra.objloader.loadOBJMeshData
import org.openrndr.math.Vector3
import java.io.File
/**
* Tangent and bitangent vectors are used in shader programs for tangent space normal mapping / lighting
* and certain forms of displacement mapping.
*
* This demo shows:
* - how to create a triangulated `MeshData`.
* - how to estimate the tangents of this MeshData.
* - How to use the tangent and bitangent attributes in GLSL code.
*/
fun main() = application {
configure {
width = 720
@@ -34,7 +43,6 @@ fun main() = application {
//x_fill.rgb = normalize(viewTangent) * 0.5 + 0.5;
x_fill.rgb = vec3(c);
""".trimIndent()
}
drawer.vertexBuffer(objVB, DrawPrimitive.TRIANGLES)

View File

@@ -0,0 +1,38 @@
package hobbycurve
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.scatter
import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.ordering.hilbertOrder
import kotlin.random.Random
/**
* Demonstrates the use of the `tensions` argument when creating a Hobby curve.
*
* The program starts by creating a random set of scattered points with enough separation between them.
* The points are sorted using `hilbertOrder` to minimize the travel distance when visiting all the points.
* Finally, we draw a set of 40 hobby translucent curves using those same points but with varying tensions.
*/
fun main() = application {
configure {
width = 720
height = 720
}
program {
extend {
for (i in -20..20) {
val t = i / 10.0
val points = drawer.bounds.offsetEdges(-50.0)
.scatter(25.0, random = Random(0))
.hilbertOrder()
drawer.stroke = ColorRGBa.WHITE.opacify(0.5)
drawer.fill = null
drawer.contour(hobbyCurve(points, closed = false, tensions = { i, inAngle, outAngle ->
Pair(t, t)
}))
}
}
}
}

View File

@@ -0,0 +1,38 @@
package hobbycurve
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.presets.WHITE_SMOKE
import org.openrndr.extra.noise.simplex
import org.openrndr.extra.noise.uniform
import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.ordering.hilbertOrder
import org.openrndr.math.Vector2
/**
* Demonstrates the creation of a 40 hobby curves with 10 points each.
* The control points in all hobby curves are almost identical, varying only
* due to a slight increase in one of the arguments of a simplex noise call.
*
* The program shows that minor displacements in control points can have
* a large impact in the resulting curve.
*/
fun main() = application {
program {
val seed = 68040
val curves = List(40) { n ->
hobbyCurve(List(10) {
Vector2(
simplex(seed, it * 13.3, n * 0.001) * 300.0 + 320.0,
simplex(seed / 2, it * 77.4, n * 0.001) * 300.0 + 240.0
)
}.hilbertOrder(), true)
}
extend {
drawer.clear(ColorRGBa.WHITE_SMOKE)
drawer.fill = null
drawer.stroke = ColorRGBa.BLACK.opacify(0.3)
drawer.contours(curves)
}
}
}

View File

@@ -0,0 +1,47 @@
package primitives
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.presets.CORAL
import org.openrndr.extra.shapes.primitives.column
import org.openrndr.extra.shapes.primitives.irregularGrid
import org.openrndr.extra.shapes.primitives.row
import kotlin.random.Random
/**
* Demonstrates how to use `Rectangle.irregularGrid()` to create a grid with varying column widths
* and row heights. The widths and heights are specified as a list of 13 `Double` values, each
* picked randomly between the values 1.0 and 4.0. This produces two types of columns and two
* types of rows only: wide ones and narrow ones.
*
* The program also demonstrates how to query a `row()` and a `column()` from a `RectangleGrid` instance,
* both of which return a `List<Rectangle>`. Both `Rectangle` lists are rendered with translucent
* colors, which makes the intersection of the column and the row slightly brighter.
*
*/
fun main() = application {
configure {
width = 720
height = 720
}
program {
extend {
val r = Random(100)
val grid = drawer.bounds.irregularGrid(
List(13) { listOf(1.0, 4.0).random(r) },
List(13) { listOf(1.0, 4.0).random(r) }
)
drawer.fill = null
drawer.stroke = ColorRGBa.WHITE
drawer.rectangles(grid.flatten())
drawer.stroke = ColorRGBa.BLACK
drawer.fill = ColorRGBa.PINK.opacify(0.5)
drawer.rectangles(grid.column(2))
drawer.fill = ColorRGBa.CORAL.opacify(0.5)
drawer.rectangles(grid.row(6))
}
}
}

View File

@@ -0,0 +1,42 @@
package primitives
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.scatter
import org.openrndr.extra.shapes.primitives.Tear
import org.openrndr.shape.Circle
/**
* Demonstrates the use of `Tear()` to create drop-like shapes out of a Vector2 point and a Circle.
*
* The tear locations are calculated using the `Rectangle.scatter()` function. Locations near the
* center of the window are filtered out.
*
* The radii of each tear is randomly chosen between three values. The orientation of each tear
* is calculated by getting the normalized difference between the tear and the center of the window,
* making them look as being emitted at the center of the window.
*/
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(40.0, distanceToEdge = 80.0).filter {
it.distanceTo(drawer.bounds.center) > 80.0
}
val tears = points.map {
val radius = listOf(5.0, 10.0, 20.0).random()
val offset = (it - drawer.bounds.center).normalized * radius
Tear(it - offset, Circle(it + offset, radius))
}
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.fill = ColorRGBa.PINK
drawer.stroke = ColorRGBa.BLACK
drawer.contours(tears.map { it.contour })
}
}
}

View File

@@ -1,6 +1,14 @@
import org.openrndr.application
import org.openrndr.extra.timer.repeat
/**
* A simple demonstration on using the `repeat` method to execute a function
* at regular intervals.
*
* Note that drawing inside the repeat action has no effect.
* See DemoRepeat02.kt to learn how to trigger drawing.
*
*/
fun main() = application {
program {
repeat(2.0) {

View File

@@ -4,7 +4,7 @@ import org.openrndr.events.Event
import org.openrndr.extra.timer.repeat
/**
* This demonstrates how to combine `repeat {}` with a postponed event to trigger drawing
* This demonstrates how to combine `repeat {}` with a postponed event to trigger drawing.
*/
fun main() = application {

View File

@@ -0,0 +1,25 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.timer.repeat
/**
* Shows how a `repeat` block can update a variable used
* for rendering. In this demo, the `opacity` variable is
* reduced on every animation frame, and increased to 1.0
* every 2 seconds, creating a pulsating animation effect.
*/
fun main() = application {
program {
var opacity = 0.0
repeat(2.0) {
opacity = 1.0
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.BLACK.opacify(opacity)
drawer.fill = ColorRGBa.WHITE.opacify(opacity)
drawer.circle(width / 2.0, height / 2.0, 200.0)
opacity *= 0.9
}
}
}

View File

@@ -1,6 +1,13 @@
import org.openrndr.application
import org.openrndr.extra.timer.timeOut
/**
* Demonstrates the `timeOut` function.
*
* It is similar to the `repeat` function,
* but it runs only once after the specified delay in seconds.
*
*/
fun main() = application {
program {
timeOut(2.0) {