diff --git a/content/docs/.DS_Store b/content/docs/.DS_Store new file mode 100644 index 0000000..b8d56ce Binary files /dev/null and b/content/docs/.DS_Store differ diff --git a/content/docs/getting-started-short.md b/content/docs/getting-started-short.md index acb21be..d00b472 100644 --- a/content/docs/getting-started-short.md +++ b/content/docs/getting-started-short.md @@ -1,5 +1,5 @@ --- -title: "hello world" +title: "Quick start" draft: false author: "Flor and Olivia" weight: 1 @@ -47,5 +47,5 @@ Hint: you can also run the code by typing `ctrl+shift+enter`. :) --> ## Next steps -For more a more in-depth introductions see [tutorial: hydra basics](../learning/video-synth-basics/getting-started). For an overview of available guides and resources, see [learning](../learning). +For more a more in-depth introductions see [tutorial: hydra basics](getting-started.md). For an overview of available guides and resources, see [learning](../learning). diff --git a/content/docs/learning/_index.md b/content/docs/learning/_index.md index e3623a9..be7917c 100644 --- a/content/docs/learning/_index.md +++ b/content/docs/learning/_index.md @@ -3,7 +3,7 @@ weight: 3 bookFlatSection: true title: "learning" bookCollapseSection: true - +# draft: true --- # learning @@ -13,14 +13,14 @@ bookCollapseSection: true ## [video synth basics](video-synth-basics) overview of hydra's [modular approach](video-synth-basics) and main function types: sources, geometry, color, blending, and modulation. -## [external sources](external-sources) -using [webcams](external-sources#using-the-webcam), [images](/external-sources/#initimage), [videos](external-sources/#initvideo), [html canvas elements](external-sources/#init), and [live streams](external-sources/#initstream) inside a hydra sketch -## [sequencing and interactivity](interactivity/_index.md) +## [external sources](basic hydra functions/external-sources.md) +using [webcams](basic hydra functions/external-sources.md#using-the-webcam), [images](/external-sources/#initimage), [videos](external-sources/#initvideo), [html canvas elements](external-sources/#init), and [live streams](external-sources/#initstream) inside a hydra sketch +## [sequencing and interactivity](interactivity) Making dynamic and interactive sketches using [arrays](interactivity/#sequencing-using-arrays), [custom functions](interactivity/#custom-functions), [audio reactivity](interactivity/#audio-reactivity), [mouse input](interactivity/#mouse-interactivity), and [MIDI controllers](interactivity/#midi). <---> -## [web editor](video-synth-basics/web-editor.md) +## [web editor](video-synth-basics/web-editor) key commands, comments, saving sketches, loading extensions and external libraries, publishing to the gallery ## [extending hydra](extending-hydra) using hydra with other javascript libraries such as P5.js, Tone.js, strudel. Loading libraries and extensions. diff --git a/content/docs/learning/getting-started/_index.md b/content/docs/learning/getting-started/_index.md new file mode 100644 index 0000000..0147901 --- /dev/null +++ b/content/docs/learning/getting-started/_index.md @@ -0,0 +1,30 @@ +--- +title: Getting Started +# bookFlatSection: true +weight: 1 +--- + +# Getting started with hydra + +This document is an introduction to making live visuals using Hydra. It covers the basics of writing code in the browser to generate and mix live video sources. No coding or video experience is necessary! + +If you just want to start in 60 seconds you can also check: +* [Getting started short version](https://hackmd.io/@r08UjGF3QMCfvNmdjuY7iQ/rJCpsbNNc) + +This tutorial is meant to be used from within the [hydra web editor](https://hydra.ojack.xyz/). It is also interactive -- you can directly modify the code in each code block to see how it affects the visuals. + +## Get to know the browser editor +To get started, open the the [hydra web editor](https://hydra.ojack.xyz/) in a separate window. Close the top window by clicking the [x] in the top right. + +![](https://i.imgur.com/ZfgVjJZ.gif) + +You will see some colorful visuals in the background with text on top in the top left of the screen. The text is code that generates the visuals behind it. + +At the right up corner you will find a toolbar with these buttons: +![](https://i.imgur.com/iCG8Lrq.png) +1. **run all code** Runs all code on the page (same as typing *ctrl+shift+enter) +2. **upload to gallery** upload a sketch to Hydra's gallery and create a shorter URL +3. **clear all** resets the environment and clears text from the editor +4. **show random sketch**. Loads random sketch examples. Always it is a good way to learn Hydra by studying someone elses code. +5. **make random change** **dices** modify values automatically. Try it with some of the sketch examples. +6. **show info window** show overlay window with help text and links diff --git a/content/docs/learning/getting-started/blending.md b/content/docs/learning/getting-started/blending.md new file mode 100644 index 0000000..242b18a --- /dev/null +++ b/content/docs/learning/getting-started/blending.md @@ -0,0 +1,182 @@ +--- +title: Combining visuals using blending and modulation +weight: 6 +--- + +## Multiple outputs + +By default, hydra contains four separate virtual outputs that can each render different visuals, and can be mixed with each other to create more complex visuals. The variables `o0`, `o1`, `o2`, and `o3` correspond to the different outputs. + +To see all four of the outputs at once, use the `render()` function. This will divide the screen into four, showing each output in a different section of the screen. + +![](https://i.imgur.com/m5Q0Na6.jpg) + +Using a different variable inside the `.out()` function renders the chain to a different output. For example, `.out(o1)` will render a function chain to graphics buffer `o1`. + + +```hydra +gradient(1).out(o0) // render a gradient to output o0 +osc().out(o1) // render voronoi to output o1 +voronoi().out(o2) // render voronoi to output o2 +noise().out(o3) // render noise to output o3 + +render() // show all outputs +``` + +By default, only output `o0` is rendered to the screen, while the `render()` command divides the screen in four. Show a specific output on the screen by adding it inside of `render()`, for example `render(o2)` to show buffer `o2`. + + +```hydra +gradient(1).out(o0) // render a gradient to output o0 +osc().out(o1) // render voronoi to output o1 +voronoi().out(o2) // render voronoi to output o2 +noise().out(o3) // render noise to output o3 + +render(o2) // show only output o2 +``` + + +*Trick: try to create different sketches and switch them in your live performance or even combine them.* + + +```hydra +gradient(1).out(o0) +osc().out(o1) +render(o0) //switch render output +// render(o1) +``` + +## Blending multiple visual sources together +You can use ***blend*** functions to combine multiple visual sources. `.blend()` combines the colors from two sources to create a third source. + +```hydra +s0.initCam() + +src(s0).out(o0) // render the webcam to output o0 + +osc(10).out(o1) // render an oscillator to output o1 + +src(o0).blend(o1).out(o2) // start with o0, mix it with o1, and send it out to o2 + +render() // render all four outputs at once +``` + +Try adding transformations to the above sources (such as `osc(10).rotate(0, 0.1).out(o1)`) to see how it affects the combined image. You can also specify the amount of blending by adding a separate parameter to `.blend()`, for example `.blend(o1, 0.9)`. + +There are multiple [blend modes](https://en.wikipedia.org/wiki/Blend_modes) in hydra, similar to blend modes you might find in a graphics program such as photoshop or gimp. See [the function reference](https://hydra.ojack.xyz/api/) for more possibilities. + +```hydra +s0.initCam() + +src(s0).out(o0) // render the webcam to output o0 + +osc(10).out(o1) // render an oscillator to output o1 + +src(o0).diff(o1).out(o2) // combine different signals by color difference (dark portions become inverted). + +render() // render all four outputs at once +``` + +--- +title: modulation + +--- + +## Modulation +While ***blend*** functions combine the colors from two visual sources, ***modulate*** functions use the colors from one source to affect the ***geometry*** of the second source. This creates a sort of warping or distorting effect. An analogy in the real world would be looking through a texture glass window. +`modulate()` does not change color or luminosity but distorts one visual source using another visual source. + +Using the same sources from above, we can use an oscillator to modulate or warp the camera image: + +```hydra +s0.initCam() + +src(s0).out(o0) // render the webcam to output o0 +osc(10).out(o1) // render an oscillator to output o1 + +src(o0).modulate(o1).out(o2) // use source o1 to distort source o0, lighter areas are distorted more + +render() // render all four outputs at once +``` + +You can add a second parameter to the `modulate()` function to control the amount of warping: `modulate(o1, 0.9)`. In this case, the red and green channels of the oscillator are being converted to x and y displacement of the camera image. + +All ***geometry*** transformations have corresponding ***modulate*** functions that allow you to use one source to warp another source. For example, `.modulateRotate()` is similar to `.rotate()`, but it allows you to apply different amounts of rotation to different parts of the visual source. See [the function reference](https://hydra.ojack.xyz/api/) for more examples. + +```hydra +s0.initCam() + +src(s0).out(o0) // render the webcam to output o0 +osc(10).out(o1) // render an oscillator to output o1 + +src(o0).modulateRotate(o1, 2).out(o2) // + +render() // render all four outputs at once +``` + +## More blending and modulating + +In addition to using multiple outputs to combine visuals, you can also combine multiple sources within the same function chain, without rendering them to separate outputs. + +```hydra +osc(10, 0.1, 1.2).blend(noise(3)).out(o0) + +render(o0) // render output o0 +``` + +This allows you to use many sources, blend modes, and modulation, all from within the same chain of functions. + +```hydra +osc(10, 0.1, 1.2).blend(noise(3)).diff(shape(4, 0.6).rotate(0, 0.1)).out() +``` + +*Trick: use `ctrl + shift + f` from the web editor to auto-format your code* + +#### Modulating with the camera +```hydra +s0.initCam() //loads a camera + +shape().modulate(src(s0)).out() //shape modulated by a camera +``` +```hydra +s0.initCam() //loads a camera + +src(s0).modulate(shape()).out() //camera modulated by a shape +``` + + + + + + +```hydra + +noise().out(o1) +shape().out(o3) + +src(o1).add(src(o3)).out(o2) //additive light. Color only gets brighter + +render() +``` + +```hydra +osc(10).out(o0) + +shape().out(o1) + +src(o0).diff(o1).out(o2) // combines different signals by color difference (color negative/inverted/opposite). + +render() +``` +```hydra +osc().mult(src(o1)).out() // multiplies the sources together, +shape(5).out(o1) + +``` + + +We have now covered all of the basic types of functions within hydra: ***source***, ***geometry***, ***color***, ***blending***, and ***modulation***! See what you can come up with by mixing these together. + + +#### Have fun! + diff --git a/content/docs/learning/getting-started/geometry-and-color.md b/content/docs/learning/getting-started/geometry-and-color.md new file mode 100644 index 0000000..dce384f --- /dev/null +++ b/content/docs/learning/getting-started/geometry-and-color.md @@ -0,0 +1,53 @@ +--- +title: geometry and color +weight: 3 +--- +## Adding transformations +We can add another transformation to the oscillator from above, by adding the function `rotate()` after the oscillator: +```hydra +osc(5,-0.126,0.514).rotate().out() +``` + +As you can see, you have first an input source `osc()` and things that come after (`rotate()` and `out()`) are connected with a dot ‘.’ +In this sense, Hydra is inspired by [modular synthesis](https://en.wikipedia.org/wiki/Modular_synthesizer). +Instead of connecting cables you connect different kinds of javascript functions. +![](https://i.imgur.com/RBRxeiL.jpg) +###### source [Sandin Image Processor](https://en.wikipedia.org/wiki/Sandin_Image_Processor) + +You can continue adding transformations to this chain of functions. For example: +```hydra +osc(5,-0.126,0.514).rotate(0, 0.2).kaleid().out() +``` + +Repeat: +```hydra +osc(5,-0.126,0.514).rotate(0, 0.2).kaleid().repeat().out() +``` + + +For more available sources and transformations, see the [interactive function reference](https://hydra.ojack.xyz/api). +The logic is to start with a ***source*** (such as `osc()`, `shape()`, or `noise()`), and then add transformations to ***geometry*** and ***color*** (such as `.rotate()`, `.kaleid()`, `.pixelate()` ), and in the end always connect the chain of transformations to the output screen `.out()` . + + +```hydra +noise(4).color(-2, 1).colorama().out() +``` + +```hydra +shape(3).repeat(3, 2).scrollX(0, 0.1).out() +``` + +## What is an error? +Sometimes, you will try to run a line of code, and nothing will happen. If you have an error you’ll notice text in red at the left-bottom on your screen. Something like ‘Unexpected token ‘.’ (in red) will appear. This doesn’t affect your code, but you won’t be able to continue coding until you fix the error. Usually it is a typing error or something related to the syntax. + +## What is a comment? + +```javascript +// Hello I’m a comment line. I’m a text that won’t change your code. You can write notations, your name or even a poem here. +``` + +## Save your sketch on the internet + + +When you evaluate the entire code with the ***run button*** or with `shift + ctrl + enter`, Hydra automatically generates a URL that contains the last changes of your sketch. You can copy and paste the url from the URL bar to save it or share it with other people. You can also use the browser `back` and `forward` arrows to navigate to earlier versions of your sketch. +![](https://i.imgur.com/lV0rmoh.png) diff --git a/content/docs/learning/getting-started/oscillator.md b/content/docs/learning/getting-started/oscillator.md new file mode 100644 index 0000000..83fac12 --- /dev/null +++ b/content/docs/learning/getting-started/oscillator.md @@ -0,0 +1,30 @@ +--- +title: drawing an oscillator +weight: 2 +--- + +## First line of code + +Use the ***clear all button*** drawing +to erase the previous sketch. + +Then, type or paste the following in the editor: +```javascript +osc().out() +``` +Press the ***run button*** drawing to run this code and update the visuals on the screen. You should see some scrolling stripes appear in the background. + +```hydra +osc().out() +``` + +This creates a visual oscillator. Try modifying the parameters of the oscillator by putting a number inside the parentheses of `osc()`, for example ```osc(10).out()```. + +Re-run the code by pressing the ***run button*** again, and seeing the visuals update. Try adding other values to control the oscillator's `frequency`, `sync`, and `color offset`. + +```hydra +osc(5, -0.126, 0.514).out() +``` + + +*Trick: you can also use the keyboard shortcut **‘ctrl + shift + enter’** to have the same effect as the run button.* \ No newline at end of file diff --git a/content/docs/learning/getting-started/webcam.md b/content/docs/learning/getting-started/webcam.md new file mode 100644 index 0000000..3709289 --- /dev/null +++ b/content/docs/learning/getting-started/webcam.md @@ -0,0 +1,32 @@ +--- +title: using the webcam +weight: 5 +--- + +## Using the webcam +In addition to using sources from within hydra (such as `osc()` and `shape()`), you can use hydra to process external video sources such as a webcam, video, or screen capture. To initialize the webcam, run the following code: +```javascript +s0.initCam() +``` + +This activates the webcam source inside a variable called `s0`, and you should see the light on your webcam light up. However, you will still not see the webcam image on the screen. In order to use the camera within a hydra sketch, you need to use it within the `src()` function. + +```hydra +s0.initCam() //initialize webcam as external source 's0' +src(s0).out() // use external source 's0' inside Hydra +``` + +Similar to adding transformations above, you can add transformations of color and geometry to the camera output, by adding functions to the chain: + +```hydra +s0.initCam() +src(s0).color(-1, 1).out() +``` + +```hydra +s0.initCam() +src(s0).color(-1, 1).kaleid().out() +``` + +If you have multiple webcams, you can access separate cameras by adding a number inside `initCam`, for example `s0.initCam(1)` or `s0.initCam(2)`. + diff --git a/content/docs/learning/guides/_index.md b/content/docs/learning/guides/_index.md index 43448bd..1514f34 100644 --- a/content/docs/learning/guides/_index.md +++ b/content/docs/learning/guides/_index.md @@ -1,17 +1,29 @@ --- bookCollapseSection: true weight: 7 -title: "guides" +title: "Guides" draft: false +# bookFlatSection: true --- - +* [Precise control of frames and timing](frames-and-timing) by geikha +* [Hydra Book: Textures](textures) by Naoto Hieda + +### how-to +* [Record hydra output](how-to/record-hydra-output) +* [Use hydra without showing the code](how-to/use-hydra-without-showing-code) + +### Developing and Contributing +* [overview](contributing) +* [hydra-synth](contributing/synth) +* [hydra-editor](contributing/editor) +* [hydra-server](contributing/server) + +## [video synth basics](video-synth-basics) +overview of hydra's [modular approach](video-synth-basics) and main function types: sources, geometry, color, blending, and modulation. +## [external sources](basic hydra functions/external-sources.md) +using [webcams](basic hydra functions/external-sources.md#using-the-webcam), [images](/external-sources/#initimage), [videos](external-sources/#initvideo), [html canvas elements](external-sources/#init), and [live streams](external-sources/#initstream) inside a hydra sketch +## [sequencing and interactivity](interactivity) +Making dynamic and interactive sketches using [arrays](interactivity/#sequencing-using-arrays), [custom functions](interactivity/#custom-functions), [audio reactivity](interactivity/#audio-reactivity), [mouse input](interactivity/#mouse-interactivity), and [MIDI controllers](interactivity/#midi). + +<---> +## [web editor](video-synth-basics/web-editor) +key commands, comments, saving sketches, loading extensions and external libraries, publishing to the gallery +## [extending hydra](extending-hydra) +using hydra with other javascript libraries such as P5.js, Tone.js, strudel. Loading libraries and extensions. +## [how-to](how-to) +a quick reference for common questions +## [guides](guides) +deeper dives into hydra topics written by members of the community. + +{{< /columns >}} diff --git a/content/docs/learning/extending-hydra.md b/content/docs/learning_old/extending-hydra.md similarity index 100% rename from content/docs/learning/extending-hydra.md rename to content/docs/learning_old/extending-hydra.md diff --git a/content/docs/learning/video-synth-basics/getting-started.md b/content/docs/learning_old/getting-started.md similarity index 99% rename from content/docs/learning/video-synth-basics/getting-started.md rename to content/docs/learning_old/getting-started.md index 9bef957..a995da2 100644 --- a/content/docs/learning/video-synth-basics/getting-started.md +++ b/content/docs/learning_old/getting-started.md @@ -1,10 +1,11 @@ --- -title: "tutorial: hydra basics" +title: "Getting started with hydra" date: 2023-04-04T15:10:36+02:00 # draft: true author: "Flor and Olivia" -weight: 1 +weight: 2 --- +# Getting started with hydra This document is an introduction to making live visuals using Hydra. It covers the basics of writing code in the browser to generate and mix live video sources. No coding or video experience is necessary! diff --git a/content/docs/learning_old/interactivity/_index.md b/content/docs/learning_old/interactivity/_index.md new file mode 100644 index 0000000..a82add0 --- /dev/null +++ b/content/docs/learning_old/interactivity/_index.md @@ -0,0 +1,243 @@ +--- +title: "Sequencing & interactivity" +draft: false +weight: 4 +# bookCollapseSection: true +--- + +# Sequencing and Interactivity +by [geikha](https://github.com/geikha) and olivia + +--- + If you're coding in Hydra, you're constantly trying many values to input to the sources and transforms, and it's just a matter of time until you like how more than one looks, and you want to somehow switch between them. We'll be referring to this idea of arguments whose value change over time as dynamic arguments. And there are two main ways to achieve this in Hydra: Arrays and functions. + +## Sequencing using Arrays + +### Sequence your inputs + + +When you send an Array as an input (indicated in javascript by `[]`), Hydra will automatically switch and jump from each element from the Array to the next one. When there are no more elements, it wraps all the way back to the beginning. Let's see it in action: + +```hydra +shape([3, 4, 5, 6, 7, 8]) + .out() +``` +### changing the speed + +The arrays in hydra have a default bpm(beats-per-minute) of 30. You can change the speed of a specific array by adding `.fast()` at the end of the array. For example `.fast(4)` will make the above array run four times faster. + +```hydra +shape([3, 4, 5, 6, 7, 8].fast(4)) + .out() +``` + +The speed of all arrays in a sketch can be changed using the `bpm` parameter of hydra synth. + +```javascript +bpm = 60 +``` + + + + + + + + + +### smooth() interpolation + +You can also interpolate between values instead of jumping from one to the other. That is, smoothly transition between values. For this you can use the `.smooth` method. It may take a Number argument (defaulted to 1) which controls the smoothness. + +```hydra +shape([3, 4, 5, 6, 7, 8].smooth()) + .out() +``` + + + + + +## Custom Functions + +Each numerical parameter in hydra can be defined as a function rather than a static variable. For example, +```javascript +osc(function(){return 100 * Math.sin(time * 0.1)}).out() +``` +modifies the oscillator frequency as a function of time. (Time is a global variable that represents the milliseconds that have passed since loading the page). + +The above example can be written more concisely using es6 syntax: + +```javascript +osc(() => 100 * Math.sin(time * 0.1)).out() +``` + + + Custom functions are especially useful for controlling hydra parameters using external inputs, such as the microphone, mouse, or midi control. + + + + + + +--- + +### Mouse interactivity + +You can have your visuals react to the position of your mouse (or finger, in touch devices). Hydra has an object called `mouse` which stores and keeps track of the position of your mouse on the webpage. + +#### mouse.x & mouse.y + +```hydra +gradient() + .hue(()=>mouse.x/3000) + .scale(1,1,()=>mouse.y/1000) + .out() +``` +| +You can refer to the pixel position of your mouse by calling `mouse.x` and `mouse.y`, each one corresponding to the horizontal and vertical coordinates respectively. When we say 'pixel position', this means that the values you'll find stored in both x and y are represented in pixels. So for `mouse.x`, this means the amount of pixels from the left edge of your window to the position of your mouse. For `mouse.y`, this means the amount of pixels between the top end of your screen and the position of your mouse. + +Many times it will be most useful to use values relative to the size of the screen. And also to have values that exist between ranges more reasonable to the hydra functions you're using. For example [-0.5; 0.5] for scrollX and scrollY, [0; 2pi] for rotation, or [0; 1] for general purposes. + +#### Note + +All of the examples using mouse position to move stuff on the canvas won't work well here, since the canvas doesn't occupy the full size of the screen as in the editor. Take this into account when we use `mouse`, that the positions are relative to the full webpage and not the canvas. This also means that as you scroll down this guide the `y` value will get higher and higher. + +#### Control anything with your mouse + +On Hydra, most values used are pretty small. So it will be way more useful to have the position of the mouse as values from 0 and 1: + +#### Getting values from 0 to 1 + +```hydra +x = () => mouse.x/width // 0→1 +y = () => mouse.y/height // 0→1 +osc() + .scale(()=>1+x()*2) + .modulate(noise(4),()=>y()/4) + .out() +``` + +You can simply multiply by `2*Math.PI` to change the range to [0; 2pi] + +#### Make something follow your mouse + +On Hydra, things are placed between 0.5 and -0.5 (left to right, top to bottom). In order for anything to follow your mouse, you'll need to get the position of your mouse between that range: + +#### Getting values from 0 to ±0.5 from the center + +```hydra +x = () => (-mouse.x/width)+.5 // 0.5→-0.5 +y = () => (-mouse.y/height)+.5 // 0.5→-0.5 +solid(255) + .diff( + shape(4,.1) + .scroll(()=>x(),()=>y()) + ) + .out() +``` + +Remember you can name these functions however you prefer. + +--- + + +```hydra +voronoi(5,.1,()=>Math.sin(time*4)) + .out() +``` + +The `time` variable seen there is a variable pre-declared by Hydra, that stores how much time passed since Hydra started in seconds. + +Functions used in Hydra don't need to be arrow functions, any no-argument function will do! Make sure your function is returning a Number to avoid errors. + +### The time variable + +When you use functions that can take numerical arguments, `time` will allow you to have their values evolve through... time. If you multiply time by some value it's as if time goes faster, while dividing while act as making time go slower. For example `Math.sin(time*4)` will go 4 times faster than `Math.sin(time)`. + +Those users more familiar with mathematics might see this as: + +* `y(t) = t` : `()=>time` +* `y(t) = A sin(f t + ph)` : `()=>amplitude*Math.sin(freq*time + phase)` + +We recommend getting familiar with some of the methods in the JS built-in `Math` object. Learn more about it [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) + + diff --git a/content/docs/learning_old/interactivity/arrays.md b/content/docs/learning_old/interactivity/arrays.md new file mode 100644 index 0000000..85d8314 --- /dev/null +++ b/content/docs/learning_old/interactivity/arrays.md @@ -0,0 +1,195 @@ +### Arrays + +#### Sequence your inputs + +When you send an Array as an input, Hydra will automatically switch and jump from each element from the Array to the next one. When there are no more elements, it wraps all the way back to the beginning. Let's see it in action: + +```hydra +osc([20,30,50,60],.1,[0,1.5]) + .out() +``` + +As you can see, the fact that both these Arrays have a different amount of values doesn't matter, Hydra will take values from each element of any Array for the same amount of time by default. + +The Arrays can be passed in any way, you may have a variable that stores an Array and use its name within your sketches (not recommended in some scenarios, more info below), you may create a function that returns Arrays and use that to automatically generate discrete sequences of values: + +```hydra +randomArray = (l=12)=> Array.from({length: l}, Math.random); +gradient() + .hue(randomArray()) + .out() +``` + +#### Changing the global bpm for Arrays + +To change how rapidly Hydra switches from element to element of all Arrays, you can change the `bpm` variable (meaning beats per minute) to any value you desire: + +```hydra +bpm = 138 // change me ! +randomArray = (l=12)=> Array.from({length: l}, Math.random); +gradient() + .hue(randomArray()) + .out() +``` + +The default value for `bpm` is 30. + +When livecoding visuals at the same time that music is playing, it can be useful to have a tapping metronome opened to keep track of the BPM being played and set this variable as such. + +#### Changing the speed of a specific Array + +Hydra adds a couple of methods to all Arrays to be used inside Hydra. `.fast` will control the speed at which Hydra takes elements from the Array. It receives a Number as argument, by which the global speed will be multiplied. So calling `.fast(1)` on an Array is the same as nothing. Higher values will generate faster switching, while lower than 1 values will be slower. + +```hydra +bpm = 45 +osc([20,30,50,60],.1,[0,1.5].fast(1.5)) // 50% faster + //.rotate([-.2,0,.2].fast(1)) // try different speeds for each array + .out() +``` + +#### Offsetting the timing of an Array + +Another one of the methods Hydra adds to Arrays, allows you to offset the timing at which Hydra will switch from one element of the Array to the next one. The method `.offset` takes a Number from 0 to 1. + +```hydra +bpm = 45 +osc([20,30,50,60],.1,[0,1.5].offset(.5)) // try changing the offset + .out() +``` + +#### Fitting the values of an Array within a range + +Sometimes you have an Array whose values aren't very useful when used as input for a some Hydra function. +Hydra adds a `.fit` method to Arrays which takes a minimum and a maximum to which fit the values into: + +```hydra +bpm = 120 +arr = ()=> [1,2,4,8,16,32,64,128,256,512] +osc(50,.1,arr().fit(0,Math.PI)) + .scale(arr().fit(1,2)) + .out() +``` + +#### Interpolating between values + +You can also interpolate between values instead of jumping from one to the other. That is, smoothly transition between values. For this you can use the `.smooth` method. It may take a Number argument (defaulted to 1) which controls the smoothness. + +```hydra +bpm = 50 +arr = [0,0.8,2] +osc(50,.1,arr.smooth()) + .rotate(arr.fit(-Math.PI/4,Math.PI/4).smooth()) + .out() +``` + +Try smoothing some of the above examples and see what happens! + +##### Easing functions + +The default interpolation used by Hydra on an Array that called `.smooth` is linear interpolation. You can select a different easing function as follows: + +```hydra +bpm = 50 +arr = [0,0.8,2] +osc(50,.1,arr.ease('easeInQuad')) + .rotate(arr.fit(-Math.PI/4,Math.PI/4).ease('easeOutQuad')) + .out() // try other easing functions ! +``` + +The following are the available easing functions: + +* linear: no easing, no acceleration +* easeInQuad: accelerating from zero velocity +* easeOutQuad: decelerating to zero velocity +* easeInOutQuad: acceleration until halfway, then deceleration +* easeInCubic +* easeOutCubic +* easeInOutCubic +* easeInQuart +* easeOutQuart +* easeInOutQuart +* easeInQuint +* easeOutQuint +* easeInOutQuint +* sin: sinusoidal shape + +#### Note on storing Arrays on variables / functions + +Storing an Array in a variable can lead to some trouble as soon as you apply some of the just-mentioned functions to it. Since Arrays are Objects, each time you call your variable, you'll be calling the same Object. If you apply some speed via `.fast` or smoothness via `.smooth` somewhere in your patch, and then use the same variable, all the following uses of the Array will also have these effects applied to them. For example + +```hydra +arr = [1,2,3] +osc(30,.1,arr.smooth()) + .rotate(arr) + .out() + +arr2 = () => [1,2,3] +osc(30,.1,arr2().smooth()) + .rotate(arr2()) + .out(o1) + +render() +``` + +#### Note on Arrays and textures + +Note that the following will not work: + +```javascript +solid(1,.5,0) + .diff([osc(),noise()]) + .out() +``` + +Hydra can't handle Arrays of textures. You can work around it in some ways: + +```hydra +solid(1,.5,0) + .diff(osc().blend(noise(),[0,1].smooth())) + .out() +``` + +Unfortunately, if you want to use many textures this solution doesn't really apply. + +Users of Hydra have come up with some experimental solutions which might come in handy in some scenarios, but they come with some drawbacks: + +```javascript +// blending method, heavy GPU load. +// every element from the array will be rendered even if not shown. +// allows for blending between elements. + +select = function(arr,l=0){ + const clamp = (num, min, max) => Math.min(Math.max(num, min), max) + const blending = (l,i)=> (clamp(l-(i-1),0,1)) + const isFunction = (typeof l === 'function') + return arr.reduce((prev,curr,i)=> + prev.blend(curr, isFunction ? ()=>blending(l(),i) : blending(l,i)) + ) +} +textures = [noise(), osc(), voronoi(), gradient()] +select(textures,()=>Math.floor(mouse.x/innerWidth*4)) + .out() +``` + +```javascript +// re-compiling method, heavy CPU load. +// it reserves an output for the switching. +// can't blend between elements. +// each time an element switches the shader must be recompiled + +osc(20) + .rotate() + .modulate(o3,.2) + .out() + +textures = [noise(), osc(), voronoi(), shape()] +index = 0 +tex = textures[index] +update = (dt)=> { + if(time % (60 / bpm) * 1000 < dt){ + index++; index %= textures.length; + tex = textures[index] + tex.out(o3) + } +} +``` \ No newline at end of file diff --git a/content/docs/learning_old/interactivity/audio.md b/content/docs/learning_old/interactivity/audio.md new file mode 100644 index 0000000..d7fc077 --- /dev/null +++ b/content/docs/learning_old/interactivity/audio.md @@ -0,0 +1,56 @@ + +## Audio reactivity +FFT functionality is available via an audio object accessed via "a". The editor uses https://github.com/meyda/meyda for audio analysis. +To show the fft bins, +```javascript +a.show() +``` +Set number of fft bins: +```javascript +a.setBins(6) +``` +Access the value of the leftmost (lowest frequency) bin: +```javascript +a.fft[0] +``` +Use the value to control a variable: +```javascript +osc(10, 0, () => a.fft[0]*4) + .out() +``` +It is possible to calibrate the responsiveness by changing the minimum and maximum value detected. (Represented by blur lines over the fft). To set minimum value detected: +```javascript +a.setCutoff(4) +``` + +Setting the scale changes the range that is detected. +```javascript +a.setScale(2) +``` +The fft[] will return a value between 0 and 1, where 0 represents the cutoff and 1 corresponds to the maximum. + +You can set smoothing between audio level readings (values between 0 and 1). 0 corresponds to no smoothing (more jumpy, faster reaction time), while 1 means that the value will never change. +```javascript +a.setSmooth(0.8) +``` +To hide the audio waveform: +```javascript +a.hide() +``` + +```javascript +a.setBins(5) // amount of bins (bands) to separate the audio spectrum + +noise(2) + .modulate(o0,()=>a.fft[1]*.5) // listening to the 2nd band + .out() + +a.setSmooth(.8) // audio reactivity smoothness from 0 to 1, uses linear interpolation +a.setScale(8) // loudness upper limit (maps to 0) +a.setCutoff(0.1) // loudness from which to start listening to (maps to 0) + +a.show() // show what hydra's listening to +// a.hide() + +render(o0) +``` diff --git a/content/docs/learning_old/interactivity/midi.md b/content/docs/learning_old/interactivity/midi.md new file mode 100644 index 0000000..c655b5b --- /dev/null +++ b/content/docs/learning_old/interactivity/midi.md @@ -0,0 +1,57 @@ +## MIDI +Hydra can be used with [Web MIDI](https://webaudio.github.io/web-midi-api/) for an extra layer of control to your visuals. + +### Example script: browser console + At this time this requires some running of code on the +browser console (Press F12 in Chrome to access). This page only considers MIDI Continuous Controllers (CC) but other types of data may be accessible. + +This is a generic script that doesn't care what Midi Channel you're broadcasting on and maps a normalized value 0.0-1.0 into an array named cc. + +This portion should be ran in the console & will register Web MIDI & map the incoming CC data to a set of parameters. For simplicity, these +parameters are named to match the CC number. The CC values are normally in a range from 0-127, but we've also normalized them to be in a range of 0.0-1.0. + +```javascript +// register WebMIDI +navigator.requestMIDIAccess() + .then(onMIDISuccess, onMIDIFailure); + +function onMIDISuccess(midiAccess) { + console.log(midiAccess); + var inputs = midiAccess.inputs; + var outputs = midiAccess.outputs; + for (var input of midiAccess.inputs.values()){ + input.onmidimessage = getMIDIMessage; + } +} + +function onMIDIFailure() { + console.log('Could not access your MIDI devices.'); +} + +//create an array to hold our cc values and init to a normalized value +var cc=Array(128).fill(0.5) + +getMIDIMessage = function(midiMessage) { + var arr = midiMessage.data + var index = arr[1] + //console.log('Midi received on cc#' + index + ' value:' + arr[2]) // uncomment to monitor incoming Midi + var val = (arr[2]+1)/128.0 // normalize CC values to 0.0 - 1.0 + cc[index]=val +} +``` + +#### Hydra script +Now that these controls have been assigned to the cc[] array, we can start using them in Hydra. As we've normalized the values 0-1 we can use +as-is with most functions or quickly remap them with various math. +```javascript +// example midi mappings - Korg NanoKontrol2 CCs + +// color controls with first three knobs +noise(4).color( ()=>cc[16], ()=>cc[17], ()=>cc[18] ).out() + +// rotate & scale with first two faders +osc(10,0.2,0.5).rotate( ()=>(cc[0]*6.28)-3.14 ).scale( ()=>(cc[1]) ).out() + +``` + +### MIDI extension diff --git a/content/docs/learning/video-synth-basics/getting-started-older.md b/content/docs/learning_old/video-synth-basics/getting-started-older.md similarity index 100% rename from content/docs/learning/video-synth-basics/getting-started-older.md rename to content/docs/learning_old/video-synth-basics/getting-started-older.md diff --git a/content/docs/learning/video-synth-basics/modular-approach.md b/content/docs/learning_old/video-synth-basics/modular-approach.md similarity index 100% rename from content/docs/learning/video-synth-basics/modular-approach.md rename to content/docs/learning_old/video-synth-basics/modular-approach.md diff --git a/content/docs/learning/video-synth-basics/web-editor.md b/content/docs/learning_old/video-synth-basics/web-editor.md similarity index 100% rename from content/docs/learning/video-synth-basics/web-editor.md rename to content/docs/learning_old/video-synth-basics/web-editor.md diff --git a/content/docs/reference/_index.md b/content/docs/reference/_index.md index 8fa5e3b..9c0a7fa 100644 --- a/content/docs/reference/_index.md +++ b/content/docs/reference/_index.md @@ -2,7 +2,7 @@ weight: 3 bookFlatSection: true title: "reference" -bookCollapseSection: false +bookCollapseSection: true --- diff --git a/content/docs/reference/api/_index.md b/content/docs/reference/api/_index.md new file mode 100644 index 0000000..7477385 --- /dev/null +++ b/content/docs/reference/api/_index.md @@ -0,0 +1,3 @@ +--- +--- + \ No newline at end of file diff --git a/content/docs/reference/api/array.md b/content/docs/reference/api/array.md new file mode 100644 index 0000000..efef69e --- /dev/null +++ b/content/docs/reference/api/array.md @@ -0,0 +1,246 @@ +--- +title: Array +date: 2023-11-16 +--- +### Arrays + +#### Sequence your inputs + +When you send an Array as an input, Hydra will automatically switch and jump from each element from the Array to the next one. When there are no more elements, it wraps all the way back to the beginning. Let's see it in action: + +```hydra +osc([20,30,50,60],.1,[0,1.5]) + .out() +``` + +As you can see, the fact that both these Arrays have a different amount of values doesn't matter, Hydra will take values from each element of any Array for the same amount of time by default. + +The Arrays can be passed in any way, you may have a variable that stores an Array and use its name within your sketches (not recommended in some scenarios, more info below), you may create a function that returns Arrays and use that to automatically generate discrete sequences of values: + +```hydra +randomArray = (l=12)=> Array.from({length: l}, Math.random); +gradient() + .hue(randomArray()) + .out() +``` + +#### Changing the global bpm for Arrays + +To change how rapidly Hydra switches from element to element of all Arrays, you can change the `bpm` variable (meaning beats per minute) to any value you desire: + +```hydra +bpm = 138 // change me ! +randomArray = (l=12)=> Array.from({length: l}, Math.random); +gradient() + .hue(randomArray()) + .out() +``` + +The default value for `bpm` is 30. + +When livecoding visuals at the same time that music is playing, it can be useful to have a tapping metronome opened to keep track of the BPM being played and set this variable as such. + +#### Changing the speed of a specific Array + +Hydra adds a couple of methods to all Arrays to be used inside Hydra. `.fast` will control the speed at which Hydra takes elements from the Array. It receives a Number as argument, by which the global speed will be multiplied. So calling `.fast(1)` on an Array is the same as nothing. Higher values will generate faster switching, while lower than 1 values will be slower. + +```hydra +bpm = 45 +osc([20,30,50,60],.1,[0,1.5].fast(1.5)) // 50% faster + //.rotate([-.2,0,.2].fast(1)) // try different speeds for each array + .out() +``` + +#### Offsetting the timing of an Array + +Another one of the methods Hydra adds to Arrays, allows you to offset the timing at which Hydra will switch from one element of the Array to the next one. The method `.offset` takes a Number from 0 to 1. + +```hydra +bpm = 45 +osc([20,30,50,60],.1,[0,1.5].offset(.5)) // try changing the offset + .out() +``` + +#### Fitting the values of an Array within a range + +Sometimes you have an Array whose values aren't very useful when used as input for a some Hydra function. +Hydra adds a `.fit` method to Arrays which takes a minimum and a maximum to which fit the values into: + +```hydra +bpm = 120 +arr = ()=> [1,2,4,8,16,32,64,128,256,512] +osc(50,.1,arr().fit(0,Math.PI)) + .scale(arr().fit(1,2)) + .out() +``` + +#### Interpolating between values + +You can also interpolate between values instead of jumping from one to the other. That is, smoothly transition between values. For this you can use the `.smooth` method. It may take a Number argument (defaulted to 1) which controls the smoothness. + +```hydra +bpm = 50 +arr = [0,0.8,2] +osc(50,.1,arr.smooth()) + .rotate(arr.fit(-Math.PI/4,Math.PI/4).smooth()) + .out() +``` + +Try smoothing some of the above examples and see what happens! + +##### Easing functions + +The default interpolation used by Hydra on an Array that called `.smooth` is linear interpolation. You can select a different easing function as follows: + +```hydra +bpm = 50 +arr = [0,0.8,2] +osc(50,.1,arr.ease('easeInQuad')) + .rotate(arr.fit(-Math.PI/4,Math.PI/4).ease('easeOutQuad')) + .out() // try other easing functions ! +``` + +The following are the available easing functions: + +* linear: no easing, no acceleration +* easeInQuad: accelerating from zero velocity +* easeOutQuad: decelerating to zero velocity +* easeInOutQuad: acceleration until halfway, then deceleration +* easeInCubic +* easeOutCubic +* easeInOutCubic +* easeInQuart +* easeOutQuart +* easeInOutQuart +* easeInQuint +* easeOutQuint +* easeInOutQuint +* sin: sinusoidal shape + +#### Note on storing Arrays on variables / functions + +Storing an Array in a variable can lead to some trouble as soon as you apply some of the just-mentioned functions to it. Since Arrays are Objects, each time you call your variable, you'll be calling the same Object. If you apply some speed via `.fast` or smoothness via `.smooth` somewhere in your patch, and then use the same variable, all the following uses of the Array will also have these effects applied to them. For example + +```hydra +arr = [1,2,3] +osc(30,.1,arr.smooth()) + .rotate(arr) + .out() + +arr2 = () => [1,2,3] +osc(30,.1,arr2().smooth()) + .rotate(arr2()) + .out(o1) + +render() +``` + +#### Note on Arrays and textures + +Note that the following will not work: + +```javascript +solid(1,.5,0) + .diff([osc(),noise()]) + .out() +``` + +Hydra can't handle Arrays of textures. You can work around it in some ways: + +```hydra +solid(1,.5,0) + .diff(osc().blend(noise(),[0,1].smooth())) + .out() +``` + +Unfortunately, if you want to use many textures this solution doesn't really apply. + +Users of Hydra have come up with some experimental solutions which might come in handy in some scenarios, but they come with some drawbacks: + +```javascript +// blending method, heavy GPU load. +// every element from the array will be rendered even if not shown. +// allows for blending between elements. + +select = function(arr,l=0){ + const clamp = (num, min, max) => Math.min(Math.max(num, min), max) + const blending = (l,i)=> (clamp(l-(i-1),0,1)) + const isFunction = (typeof l === 'function') + return arr.reduce((prev,curr,i)=> + prev.blend(curr, isFunction ? ()=>blending(l(),i) : blending(l,i)) + ) +} +textures = [noise(), osc(), voronoi(), gradient()] +select(textures,()=>Math.floor(mouse.x/innerWidth*4)) + .out() +``` + +```javascript +// re-compiling method, heavy CPU load. +// it reserves an output for the switching. +// can't blend between elements. +// each time an element switches the shader must be recompiled + +osc(20) + .rotate() + .modulate(o3,.2) + .out() + +textures = [noise(), osc(), voronoi(), shape()] +index = 0 +tex = textures[index] +update = (dt)=> { + if(time % (60 / bpm) * 1000 < dt){ + index++; index %= textures.length; + tex = textures[index] + tex.out(o3) + } +} +--- +``` + +## available methods for Arrays + +### fast +fast( speed = 1 ) + +```hydra +// default +osc([10,30,60].fast(2),0.1,1.5).out(o0) +``` + +### smooth +smooth( smooth = 1 ) + +```hydra +// default +shape(999).scrollX([-0.2,0.2].smooth()).out(o0) +``` + +### ease +ease( ease = 'linear' ) + +```hydra +// default +shape(4).rotate([-3.14,3.14].ease('easeInOutCubic')).out(o0) +``` + +### offset +offset( offset = 0.5 ) + +```hydra +// default +shape(999).scrollY(.2).scrollX([-0.2,0.2]) + .add( + shape(4).scrollY(-.2).scrollX([-0.2,0.2].offset(0.5)) + ).out(o0) +``` + +### fit +fit( low = 0, high = 1 ) + +```hydra +// default +shape().scrollX([0,1,2,3,4].fit(-0.2,0.2)).out(o0) +``` + diff --git a/content/docs/reference/api/audio.md b/content/docs/reference/api/audio.md new file mode 100644 index 0000000..5b773e3 --- /dev/null +++ b/content/docs/reference/api/audio.md @@ -0,0 +1,113 @@ + +## Audio reactivity +FFT functionality is available via an audio object accessed via "a". The editor uses https://github.com/meyda/meyda for audio analysis. +To show the fft bins, +```javascript +a.show() +``` +Set number of fft bins: +```javascript +a.setBins(6) +``` +Access the value of the leftmost (lowest frequency) bin: +```javascript +a.fft[0] +``` +Use the value to control a variable: +```javascript +osc(10, 0, () => a.fft[0]*4) + .out() +``` +It is possible to calibrate the responsiveness by changing the minimum and maximum value detected. (Represented by blur lines over the fft). To set minimum value detected: +```javascript +a.setCutoff(4) +``` + +Setting the scale changes the range that is detected. +```javascript +a.setScale(2) +``` +The fft[] will return a value between 0 and 1, where 0 represents the cutoff and 1 corresponds to the maximum. + +You can set smoothing between audio level readings (values between 0 and 1). 0 corresponds to no smoothing (more jumpy, faster reaction time), while 1 means that the value will never change. +```javascript +a.setSmooth(0.8) +``` +To hide the audio waveform: +```javascript +a.hide() +``` + +```javascript +a.setBins(5) // amount of bins (bands) to separate the audio spectrum + +noise(2) + .modulate(o0,()=>a.fft[1]*.5) // listening to the 2nd band + .out() + +a.setSmooth(.8) // audio reactivity smoothness from 0 to 1, uses linear interpolation +a.setScale(8) // loudness upper limit (maps to 0) +a.setCutoff(0.1) // loudness from which to start listening to (maps to 0) + +a.show() // show what hydra's listening to +// a.hide() + +render(o0) +``` + +--- + +## available Audio methods + +### fft +fft = Array(4) + +```javascript +// default +osc().modulate(noise(3),()=>a.fft[0]).out(o0) +``` + +### setSmooth +setSmooth( smooth = 0.4 ) + +```javascript +// default +a.setSmooth(0.8) +osc().modulate(noise(3),()=>a.fft[0]).out(o0) +``` + +### setCutoff +setCutoff( cutoff = 2 ) + +```javascript +// threshold +a.setCutoff(4) +osc().modulate(noise(3),()=>a.fft[0]).out(o0) +``` + +### setBins +setBins( numBins = 4 ) + +```javascript +// change color with hissing noise +a.setBins(8) +osc(60,0.1,()=>a.fft[7]*3).modulate(noise(3),()=>a.fft[0]).out(o0) +``` + +### setScale +setScale( scale = 10 ) + +```javascript +// the smaller the scale is, the bigger the output is +a.setScale(5) +osc().modulate(noise(3),()=>a.fft[0]).out(o0) +``` + +### hide +hide( ) + +### show +show( ) + + + diff --git a/content/docs/reference/api/color.md b/content/docs/reference/api/color.md new file mode 100644 index 0000000..8b90f0f --- /dev/null +++ b/content/docs/reference/api/color.md @@ -0,0 +1,140 @@ +--- +title: Color +date: 2023-11-16 +weight: 3 +--- +# Color + +### posterize +posterize( bins = 3, gamma = 0.6 ) + +```hydra +// static gradient posterized, varying bins +gradient(0).posterize( [1, 5, 15, 30] , 0.5 ).out(o0) +``` + +### shift +shift( r = 0.5, g, b, a ) + +```hydra +// default +osc().shift(0.1,0.9,0.3).out() +``` + +### invert +invert( amount = 1 ) + +Invert color. +```hydra +// default +solid(1,1,1).invert([0,1]).out(o0) +``` + +### contrast +contrast( amount = 1.6 ) + +Larger amount value makes higher contrast. +```hydra +// 20Hz oscillator with contrast interpolating between 0.0-5.0 +osc(20).contrast( () => Math.sin(time) * 5 ).out(o0) +``` + +### brightness +brightness( amount = 0.4 ) + +```hydra +// default +osc(20,0,2) + .brightness( () => Math.sin(time) ) + .out(o0) +``` + +### luma +luma( threshold = 0.5, tolerance = 0.1 ) + +```hydra +// default +osc(10,0,1).luma(0.5,0.1).out(o0) +``` + +### thresh +thresh( threshold = 0.5, tolerance = 0.04 ) + +```hydra +// default +noise(3,0.1).thresh(0.5,0.04).out(o0) +``` + +### color +color( r = 1, g = 1, b = 1, a = 1 ) + +```hydra +// default +osc().color(1,0,3).out(o0) +``` + +### saturate +saturate( amount = 2 ) + +```hydra +// default +osc(10,0,1).saturate( () => Math.sin(time) * 10 ).out(o0) +``` + +### hue +hue( hue = 0.4 ) + +```hydra +// default +osc(30,0.1,1).hue(() => Math.sin(time)).out(o0) +``` + +### colorama +colorama( amount = 0.005 ) + +Shift HSV values. +```hydra +// // 20Hz oscillator source +// // color sequence of Red, Green, Blue, White, Black +// // colorama sequence of 0.005, 0.5, 1.0 at 1/8 speed +// // output to buffer o0 +osc(20) + .color([1,0,0,1,0],[0,1,0,1,0],[0,0,1,1,0]) + .colorama([0.005,0.33,0.66,1.0].fast(0.125)) + .out(o0) +``` + +### sum +sum( scale = 1 ) + + + +### r +r( scale = 1, offset ) + +```hydra +// default +osc(60,0.1,1.5).layer(gradient().r()).out(o0) +``` + +### g +g( scale = 1, offset ) + +```hydra +// default +osc(60,0.1,1.5).layer(gradient().g()).out(o0) +``` + +### b +b( scale = 1, offset ) + +```hydra +// default +osc(60,0.1,1.5).layer(gradient().colorama(1).b()).out(o0) +``` + +### a +a( scale = 1, offset ) + + + diff --git a/content/docs/reference/api/combine.md b/content/docs/reference/api/combine.md new file mode 100644 index 0000000..e4df73f --- /dev/null +++ b/content/docs/reference/api/combine.md @@ -0,0 +1,81 @@ +--- +title: Blend +date: 2023-11-16 +--- +# Blend + +### add +add( texture, amount = 1 ) + + +Add textures. +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// default +shape().scale(0.5).add(shape(4),[0,0.25,0.5,0.75,1]).out(o0) +``` + +### sub +sub( texture, amount = 1 ) + +```hydra +// default +osc().sub(osc(6)).out(o0) +``` + +### layer +layer( texture ) + +Overlay texture based on alpha value. +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// default +solid(1,0,0,1).layer(shape(4).color(0,1,0,()=>Math.sin(time*2))).out(o0) +``` + +### blend +blend( texture, amount = 0.5 ) + + +Blend textures. +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// default +shape().scale(0.5).blend(shape(4),[0,0.25,0.5,0.75,1]).out(o0) +``` + +### mult +mult( texture, amount = 1 ) + + +Multiply images and blend with the texture by `amount`. +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// default +osc(9,0.1,2).mult(osc(13,0.5,5)).out() +``` + +### diff +diff( texture ) + + +Return difference of textures. +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// default +osc(9,0.1,1).diff(osc(13,0.5,5)).out(o0) +``` + +### mask +mask( texture ) + +```hydra +// default +gradient(5).mask(voronoi(),3,0.5).invert([0,1]).out(o0) +``` + diff --git a/content/docs/reference/api/combineCoord.md b/content/docs/reference/api/combineCoord.md new file mode 100644 index 0000000..fa21ce5 --- /dev/null +++ b/content/docs/reference/api/combineCoord.md @@ -0,0 +1,173 @@ +--- +title: Modulate +date: 2023-11-16 +--- +# Modulate + +### modulateRepeat +modulateRepeat( texture, repeatX = 3, repeatY = 3, offsetX = 0.5, offsetY = 0.5 ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// default +shape(4,0.9) + .mult(osc(3,0.5,1)) + .modulateRepeat(osc(10), 3.0, 3.0, 0.5, 0.5) + .out(o0) +``` + +### modulateRepeatX +modulateRepeatX( texture, reps = 3, offset = 0.5 ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// straight lines illusion +shape(4,0.9) + .mult(osc(4,0.25,1)) + .modulateRepeatX(osc(10), 5.0, ({time}) => Math.sin(time) * 5) + .scale(1,0.5,0.05) + .out(o0) +``` + +### modulateRepeatY +modulateRepeatY( texture, reps = 3, offset = 0.5 ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// morphing grid +shape(4,0.9) + .mult(osc(4,0.25,1)) + .modulateRepeatY(osc(10), 5.0, ({time}) => Math.sin(time) * 5) + .scale(1,0.5,0.05) + .out(o0) +``` + +### modulateKaleid +modulateKaleid( texture, nSides = 4 ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +See also: [`kaleid`](#kaleid). +```hydra +// default +osc(9,-0.1,0.1) + .modulateKaleid(osc(11,0.5,0),50) + .scale(0.1,0.3) + .modulate(noise(5,0.1)) + .mult(solid(1,1,0.3)) + .out(o0) +``` + +### modulateScrollX +modulateScrollX( texture, scrollX = 0.5, speed ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +See also: [`scrollX`](#scrollX) +```hydra +// default +voronoi(25,0,0) + .modulateScrollX(osc(10),0.5,0) + .out(o0) +``` + +### modulateScrollY +modulateScrollY( texture, scrollY = 0.5, speed ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +See also: [`scrollY`](#scrollY) +```hydra +// default +voronoi(25,0,0) + .modulateScrollY(osc(10),0.5,0) + .out(o0) +``` + +### modulate +modulate( texture, amount = 0.1 ) + + +Modulate texture. +More about modulation at: +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +// chocolate whirlpool +voronoi() + .color(0.9,0.25,0.15) + .rotate(({time})=>(time%360)/2) + .modulate(osc(25,0.1,0.5) + .kaleid(50) + .scale(({time})=>Math.sin(time*1)*0.5+1) + .modulate(noise(0.6,0.5)), + 0.5) + .out(o0) +``` + +### modulateScale +modulateScale( texture, multiple = 1, offset = 1 ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +See also: [`scale`](#scale). +```hydra +// cosmic radiation +gradient(5).repeat(50,50).kaleid([3,5,7,9].fast(0.5)) + .modulateScale(osc(4,-0.5,0).kaleid(50).scale(0.5),15,0) + .out(o0) +``` + +### modulatePixelate +modulatePixelate( texture, multiple = 10, offset = 3 ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +See also: [`pixelate`](#pixelate) +```hydra +// what lies beneath +voronoi(10,1,5).brightness(()=>Math.random()*0.15) + .modulatePixelate(noise(25,0.5),100) + .out(o0) +``` + +### modulateRotate +modulateRotate( texture, multiple = 1, offset ) + + +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +See also: [`rotate`](#rotate) +```hydra +// wormhole +voronoi(100,3,5) + .modulateRotate(osc(1,0.5,0).kaleid(50).scale(0.5),15,0) + .mult(osc(50,-0.1,8).kaleid(9)) + .out(o0) +``` + +### modulateHue +modulateHue( texture, amount = 1 ) + + +Changes coordinates based on hue of second input. Based on: https://www.shadertoy.com/view/XtcSWM +The `texture` parameter can be any kind of [source](#sources), for +example a [`color`](#color), [`src`](#src), or [`shape`](#shape). +```hydra +src(o0) + .modulateHue(src(o0).scale(1.01),1) + .layer(osc(4,0.5,2).mask(shape(4,0.5,0.001))) + .out(o0) +``` + diff --git a/content/docs/reference/api/coord.md b/content/docs/reference/api/coord.md new file mode 100644 index 0000000..8e3647a --- /dev/null +++ b/content/docs/reference/api/coord.md @@ -0,0 +1,91 @@ +--- +title: Geometry +date: 2023-11-16 +weight: 2 +--- +# Geometry + +### rotate +rotate( angle = 10, speed ) + +Rotate texture. +```hydra +// constant rotation +osc(50).rotate( () => time%360 ).out(o0) +``` + +### scale +scale( amount = 1.5, xMult = 1, yMult = 1, offsetX = 0.5, offsetY = 0.5 ) + +Scale texture. +```hydra +// default +shape().scale(1.5,1,1).out(o0) +``` + +### pixelate +pixelate( pixelX = 20, pixelY = 20 ) + +Pixelate texture with `pixelX` segments and `pixelY` segments. +```hydra +// default +noise().pixelate(20,20).out(o0) +``` + +### repeat +repeat( repeatX = 3, repeatY = 3, offsetX, offsetY ) + +```hydra +// default +shape().repeat(3.0, 3.0, 0.0, 0.0).out() +``` + +### repeatX +repeatX( reps = 3, offset ) + +```hydra +// default +shape().repeatX(3.0, 0.0).out() +``` + +### repeatY +repeatY( reps = 3, offset ) + +```hydra +// default +shape().repeatY(3.0, 0.0).out() +``` + +### kaleid +kaleid( nSides = 4 ) + +Kaleidoscope effect with `nSides` repetition. +```hydra +// default +osc(25,-0.1,0.5).kaleid(50).out(o0) +``` + +### scroll +scroll( scrollX = 0.5, scrollY = 0.5, speedX, speedY ) + +```hydra +// default +shape(3).scroll(0.1,-0.3).out(o0) +``` + +### scrollX +scrollX( scrollX = 0.5, speed ) + +```hydra +// default +osc(10,0,1).scrollX(0.5,0).out(o0) +``` + +### scrollY +scrollY( scrollY = 0.5, speed ) + +```hydra +// default +osc(10,0,1).scrollY(0.5,0).out(o0) +``` + diff --git a/content/docs/learning/external-sources.md b/content/docs/reference/api/external-sources.md similarity index 94% rename from content/docs/learning/external-sources.md rename to content/docs/reference/api/external-sources.md index 6b7fbaf..60bc1f4 100644 --- a/content/docs/learning/external-sources.md +++ b/content/docs/reference/api/external-sources.md @@ -1,12 +1,11 @@ --- -title: "external sources: cameras, videos, streams" +title: "External sources" draft: false -author: "geikha" weight: 4 --- # External Sources -by [geikha](https://github.com/geikha) and [olivia](https://ojack.xyz) + ## Using the webcam In addition to using sources from within hydra (such as `osc()` and `shape()`), you can use hydra to process external video sources such as a webcam. External sources in hydra are referenced using predefined objects `s0`, `s1`, `s2`, and `s3`. To initialize the webcam in `s0`, run the following code: ```javascript @@ -37,8 +36,9 @@ If you have multiple webcams, you can access separate cameras by adding a number --- +## Available source functions -## initCam() +### initCam() You can use a webcam's video as such: @@ -52,7 +52,7 @@ s0.initCam(2) // if you have many cameras, you can select one specifically --- -## initImage() +### initImage() Load an image into a source object: @@ -70,11 +70,11 @@ When running Hydra in Atom, or any other local manner, you can load local files s0.initImage("file:///home/user/Images/image.png") ``` -### Supported formats +### Supported image formats You can load `.jpeg`, `.png`, and `.bmp` as well as `.gif` and `.webp` (although animation won't work). -## initVideo() +### initVideo() The syntax for loading video is the same as for loading image, only changing the function to `loadVideo`: @@ -83,10 +83,12 @@ s0.initVideo("https://media.giphy.com/media/AS9LIFttYzkc0/giphy.mp4") src(s0).out() ``` -### Supported formats +### Supported video formats You can load `.mp4`, `.ogg` and `.webm` videos. +{{< youtube bavUH1cv_v0 >}} + ### Useful HTML Video properties You can access all of the [HTML Video](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) functions when a video is loaded to a Source via `s0.src`. Some useful properties are: @@ -97,7 +99,7 @@ s0.src.currentTime = 10 // seek to the 10th second s0.src.loop = false // don't loop the video ``` -## initScreen() +#### initScreen() You can capture your screen or specific windows or tabs to use as a video source: @@ -107,7 +109,9 @@ src(s0).out() ``` --- -## init() +{{< youtube mPH8hpbEs3o >}} + +### init() `init()` is a more generic function for loading any external source into hydra. This can be especially useful when you are using an [HTML canvas element](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) as an input, or loading an existing resource as a source into hydra. Valid input types are documented in the [regl texture documentation](http://regl.party/api#textures). For example, the following code creates a canvas element and draws text to it, and then uses that canvas as a source in hydra: @@ -124,7 +128,7 @@ src(s0).diff(osc(2, 0.1, 1.2)).out() ``` use the `dynamic` parameter to indicate whether the source will be updated, or remain the same. -## initStream() +### initStream() {{< hint danger >}} note: initStream() is currently broken in hydra editor due to server issues {{< /hint >}} @@ -133,13 +137,13 @@ streaming between Hydra sessions Hydra (the editor) also has built-in streaming. You can stream the output of your Hydra to someone else and vice-versa. This is done in a similar fashion to using images and videos, using external sources. But there are some extra steps for streaming: -### The pb object +#### The pb object On your Hydra editor, you can find a pre-defined object called `pb` (as in patch-bay). This object basically represents the connection of your Hydra editor instance to all others hosted on the same server. When you want to share your stream to someone else you'll have to give your Hydra session a name. Do this using the `pb.setName()` function and by passing in some string as the name. For example: `pb.setName('myverycoolsession')`. If you want someone else to stream to you, ask them to set a name as such and share it with you. You can see online sessions using the function `pb.list()`, which will return an Array of names. -### Starting to stream +#### Starting to stream Streaming is as simple as initiating the source as a stream and passing the name of the session you want to stream. For example: @@ -151,7 +155,7 @@ src(s0) --- -## Extra parameters +### Extra parameters Any external sources loaded into Hydra are using [regl's texture constructor](https://github.com/regl-project/regl/blob/master/API.md#textures) in the background. There are many properties you can set when loading a texture and Hydra and regl handle the important ones for you. But to set any of these properties you can pass an object containing them to any of the init functions. For example: diff --git a/content/docs/reference/api/settings.md b/content/docs/reference/api/settings.md new file mode 100644 index 0000000..e81189e --- /dev/null +++ b/content/docs/reference/api/settings.md @@ -0,0 +1,118 @@ +--- +title: Synth Settings +date: 2023-11-16 +--- +# Synth Settings +Functions and settings that affect overall hydra behavor and rendering. + +### render +render( texture = all ) + +```javascript +// default +osc(30,0.1,1.5).out(o0) +noise().out(o1) +solid(1).out(o2) +gradient().out(o3) +render() +``` + +### update +update( ) + +```hydra +// update is called every frame +b = 0 +update = () => b += 0.01 * Math.sin(time) +shape().scrollX(()=>b).out(o0) +``` + +### setResolution +setResolution( width, height ) + +```javascript +// make the canvas small (100 pixel x 100 pixel) +setResolution(100,100) +osc().out(o0) +``` + +### hush +hush( ) + +```javascript +// clear the buffers +osc().out(o0) +hush() +``` + +### setFunction +setFunction( options ) + +```hydra +// from https://www.shadertoy.com/view/XsfGzn +setFunction({ + name: 'chroma', + type: 'color', + inputs: [ + ], + glsl: ` + float maxrb = max( _c0.r, _c0.b ); + float k = clamp( (_c0.g-maxrb)*5.0, 0.0, 1.0 ); + float dg = _c0.g; + _c0.g = min( _c0.g, maxrb*0.8 ); + _c0 += vec4(dg - _c0.g); + return vec4(_c0.rgb, 1.0 - k); +`}) +osc(60,0.1,1.5).chroma().out(o0) +``` + +### speed +speed = 1 + +```hydra +// change overall speed +speed = 3 +osc(60,0.1,[0,1.5]).out(o0) +``` + +### bpm +bpm = 30 + +```hydra +// change array speed +bpm = 60 +osc(60,0.1,[0,1.5]).out(o0) +``` + +### width +width + +```hydra +shape(99).scrollX(() => -mouse.x / width).out(o0) +``` + +### height +height + +```hydra +shape(99).scrollY(() => -mouse.y / height).out(o0) +``` + +### time +time + +```hydra +// default +shape(2,0.8).kaleid(()=>6+Math.sin(time)*4).out(o0) +``` + +### mouse +mouse = { x, y } + +```hydra +shape(99).scroll( + () => -mouse.x / width, + () => -mouse.y / height) + .out(o0) +``` + diff --git a/content/docs/reference/api/src.md b/content/docs/reference/api/src.md new file mode 100644 index 0000000..5bb4ba2 --- /dev/null +++ b/content/docs/reference/api/src.md @@ -0,0 +1,80 @@ +--- +title: Sources +date: 2023-11-16 +weight: 1 +--- +# Source + +### noise +noise( scale = 10, offset = 0.1 ) + +Generate [Perlin noise](https://en.wikipedia.org/wiki/Perlin_noise). +```hydra +// default +noise(10, 0.1).out(o0) +``` + +### voronoi +voronoi( scale = 5, speed = 0.3, blending = 0.3 ) + +Generate [voronoi shapes](https://en.wikipedia.org/wiki/Voronoi_diagram). +```hydra +// default +voronoi(5,0.3,0.3).out(o0) +``` + +### osc +osc( frequency = 60, sync = 0.1, offset ) + +```hydra +// frequency +osc( [1,10,50,100,250,500].fast(2) ).out(o0) +``` + +### shape +shape( sides = 3, radius = 0.3, smoothing = 0.01 ) + +```hydra +// triangle +shape(3,0.5,0.001).out(o0) +``` + +### gradient +gradient( speed ) + +```hydra +// gradient sequence at speeds of 1, 2 & 4 +gradient([1,2,4]).out(o0) +``` + +### src +src( tex ) + +See `hydra-examples` repository +```hydra +// feedback +src(o0).modulate(noise(3),0.005).blend(shape(4),0.01).out(o0) +``` + +### solid +solid( r, g, b, a = 1 ) + +```hydra +// cycling through red, green and blue +solid([1,0,0],[0,1,0],[0,0,1],1).out(o0) +``` + +### prev +prev( ) + + + +### out +out( texture = all ) + +```hydra +// default +osc().out(o1) +src(o1).out(o0) +``` + diff --git a/content/docs/reference/web-editor.md b/content/docs/reference/web-editor.md new file mode 100644 index 0000000..a930bcc --- /dev/null +++ b/content/docs/reference/web-editor.md @@ -0,0 +1,61 @@ +--- +title: "using the web editor" +date: 2023-04-04T15:10:36+02:00 +draft: false +author: "Flor and Olivia" +weight: 6 +--- + +# Web editor +basics of the browser editor at https://hydra.ojack.xyz + +## key commands +* CTRL-Enter: run a line of code +* CTRL-Shift-Enter: run all code on screen +* ALT-Enter: run a block +* CTRL-Shift-H: hide or show code +* CTRL-Shift-F: format code using [Prettier](https://prettier.io/) +* CTRL-Shift-S: Save screenshot and download as local file. The +* CTRL-Shift-G: Share to twitter (if available). Shares to [@hydra_patterns](https://twitter.com/hydra_patterns) + +## toolbar +At the right up corner you will find a toolbar with these buttons: +![](https://i.imgur.com/iCG8Lrq.png) +1. **run all code** Runs all code on the page (same as typing *ctrl+shift+enter) +2. **upload to gallery** upload a sketch to Hydra's gallery and create a shorter URL +3. **clear all** resets the environment and clears text from the editor +4. **show random sketch**. Loads random sketch examples. Always it is a good way to learn Hydra by studying someone elses code. +5. **make random change** **dices** modify values automatically. Try it with some of the sketch examples. +6. **show info window** show overlay window with help text and links + + +## share your sketch +When you evaluate the entire code with the ***run button*** or with `shift + ctrl + enter`, Hydra automatically generates a URL that contains the last changes of your sketch. You can copy and paste the url from the URL bar to save it or share it with other people. You can also use the browser `back` and `forward` arrows to navigate to earlier versions of your sketch. +![](https://i.imgur.com/lV0rmoh.png) + +## sharing with the code hidden +The `showCode=false` url flag makes it possible to share a sketch with the code hidden. + +For example, the following sketch +```javascript +osc(10, 0.1, 1.2).modulateScale(noise(3)).out() +``` + +is available at the URL +https://hydra.ojack.xyz/?code=b3NjKDEwJTJDJTIwMC4xJTJDJTIwMS4yKS5tb2R1bGF0ZVNjYWxlKG5vaXNlKDMpKS5vdXQoKQ%3D%3D + + +this URL will correspond to the same sketch, but with the code and toolbar hidden: +https://hydra.ojack.xyz/?code=b3NjKDEwJTJDJTIwMC4xJTJDJTIwMS4yKS5tb2R1bGF0ZVNjYWxlKG5vaXNlKDMpKS5vdXQoKQ%3D%3D&showCode=false + +pressing `Ctrl+Shift+h` will show the code again + + +## What is an error? +Sometimes, you will try to run a line of code, and nothing will happen. If you have an error you’ll notice text in red at the left-bottom on your screen. Something like ‘Unexpected token ‘.’ (in red) will appear. This doesn’t affect your code, but you won’t be able to continue coding until you fix the error. Usually it is a typing error or something related to the syntax. + +## What is a comment? + +```javascript +// Hello I’m a comment line. I’m a text that won’t change your code. You can write notations, your name or even a poem here. +```