The hydra-colorspaces extension adds lots of functions to work with color in many different colorspaces.
Colorspace | Elements | Stands for | Range | Description |
---|---|---|---|---|
rgb | r,g,b,a | Red, Green, Blue, Alpha | [0;1] [0;1] [0;1] [0;1] | Good old RGBA |
cmyk | c,m,y,k | Cyan, Magenta, Yellow, Key | [0;1] [0;1] [0;1] [0;1] | Substractive colorspace used in print |
hsv | h,s,v | Hue, Saturation, Value (Brightness) | [0;1] [0;1] [0;1] | Cylindrical colorspace where saturation peaks when brightness is 1 |
hsl | h,s,l | Hue, Saturation, Lightness | [0;1] [0;1] [0;1] | Cylindrical colorspace where saturation peaks when lightness is 0.5 |
yuv | y,u,v | Luminance, Blue difference, Red difference | [0;1] [-0.5;+0.5] [-0.5;+0.5] | Color model used in PAL systems |
yiq | y,i,q | Luminance, In-phase, Quadrature | [0;1] [-0.5;+0.5] [-0.5;+0.5] | Color model used in NTSC systems |
Here are all the functions written for quick reference, exemplified using the hsv
colorspace and the h
element, however these apply to any colorspace and any element within it:
// solid
hsv(1,0.5,1,1).out()
// color
gradient().hsv(1,0.5,1).out()
gradient().hsv.offset(.5,0,-.2).out()
gradient().hsv.invert(1,0,1).out()
gradient().hsv.to().out()
gradient().hsv.from().out()
// element specific
gradient().hsv.h().out()
gradient().hsv.hMult(2).out()
gradient().hsv.hOffset(.2).out()
gradient().hsv.hInvert().out()
gradient().hsv.hSet(0.3).out()
gradient().hsv.hFrom(osc()).out()
gradient().hsv.hMultFrom(osc(),1.5).out()
gradient().hsv.hOffsetFrom(noise(),0.2).out()
gradient().hsv.hKey(0.2).out()
gradient().hsv.hWith(x=>x.pixelate()).out()
This extensions automatically defines functions for the different colorspaces, so listing them all wouldn't make sense. Instead of naming each colorspace, for the purpose of this documentation, I'll be generically referring to all color spaces as cs
, and to any of their elements as el
. For example, instead of .cmyk.cOffset()
, which offsets the Cyan element in the CMYK colorspace, I'll write .cs.elOffset()
.
If you read el
as the argument for a function, it means there's an argument for each element of the colorspace in order. For example, cs(el,alpha)
would mean yuv(y,u,v,alpha)
for that colorspace.
Some functions add alpha as a last argument after the elements of the colorspace. This doesn't apply to RGBA, given it already has alpha in it. For example cs(el=0, alpha=1)
means rgb(r=0,g=0,b=0,a=1)
.
cs( el = 0, alpha = 1 )
- Example:
hsv(()=>time,1,1).out()
- Alias:
cs_solid()
These functions will act similarly to Hydra's solid()
function, letting you write a particular color in the given colorspace and filling the screen with it.
.cs( el = 1, alpha = 1 )
- Example:
osc(20,.1,2).yuv(1,1,0).out()
- Alias:
.cs.color()
,.cs_color()
These functions will act similarly to Hydra's .color()
function, allowing you to multiply the value of each element in the colorspace.
.cs.elMult( amt = 1 )
- Example:
gradient().hsl.sMult(.8).out()
- Alias:
.cs_el_mult()
.cs.offset( el = 0, alpha = 0 )
- Example:
gradient().hsv.offset(.5,-.2,.5).out()
- Alias:
.cs_offset()
Offset an element by a given amount. Basically adds the number you give it to the corresponding element.
.cs.elOffset()
- Example:
osc().yiq.qOffset(.2).out()
- Alias:
.cs_el_offset()
.cs.invert( el = 1, alpha = 0 )
- Example:
gradient().cmyk.invert(1,0,1,0).out()
- Alias:
.cs_invert()
Invert an element by a given amount. The argument sets interpolation between the original color and the inverted one, that's why the default for elements is 1 while alpha is 0. An inversion here means 1.0 - el
for most elements. For those elements with a bipolar range, inversion is done by calculating 0.0 - el
instead.
.cs.elInvert()
- Example:
osc(5,.1,2).yiq.qInvert().out()
- Alias:
.cs_el_invert()
.cs.to()
- Example:
gradient().cmyk.to().out()
- Alias:
.cs_to()
Converts the color values of the texture which calls the method to the given colorspace.
.cs.from()
- Example:
gradient().add(solid(0,0,1)).hsv.from().out()
- Alias:
.cs_from()
Let's you convert back to RGBA, or interpret any color values as if they were from the given colorspace.
.cs.el()
- Example:
osc(40,.1,Math.PI/2).hsv.h().out()
- Alias:
.cs_el()
These functions will work in the same way as Hydra's r()
, b()
, g()
, and a()
functions. They will simply replicate the given element's value in all channels except alpha and return an opaque image.
.cs.elSet( value = 1 )
- Example:
osc(8,.1,2).hsv.sSet(.5).out()
- Alias:
.cs_el_set()
Allows you to set the given element to a fixed value for all pixels. Shown in the example being used to set the saturation of a texture.
Note: All the modulating functions take only the first value from the texture, or in other words, the red channel. If you want to modulate by another element in the given texture, simply retrieve that element from the texture as shown just above.
.cs.elFrom( texture , amt = 1 )
- Example:
rgb(1,0,0).hsl.sFrom(osc(9)).out()
- Alias:
.cs_el_from()
Will set the value of the element to the value in the given texture. The amt
argument allows you to interpolate between the original value for the element and the texture's value.
.cs.elMultFrom( texture, amt = 1 )
- Example:
gradient().hsl.sMultFrom(osc(9)).out()
- Alias:
.cs_el_mult_from()
Will multiply the given element's value by the given texture. The texture's value will be multiplied by the amt
parameter.
.cs.elOffsetFrom( texture, amt = 1 )
- Example:
gradient().hsl.hOffsetFrom(noise(1,2),.2).out()
- Alias:
.cs_el_mult_from()
Will add the texture to the given value. The texture's value will be multiplied by the amt
parameter.
.cs.elKey( topThreshold = 0.5 , topTolerance = 0.05 , bottomThreshold = 0 , bottomTolerance = 0 )
- Example:
solid().layer(gradient(1).rgb.rKey(.5,0)).out()
- Alias:
.cs_el_key()
Similar to Hydra's luma()
, but instead of keying by luminance, you can key by any element. THese functions will turn transparent any pixel where the given element isn't between the top threshold and the bottom threshold.
Note: These functions work with straight alpha, so you might not see changes directly on screen unless you layer it over something else. Similarly to how osc().color(1,1,1,0).out()
still appears on screen even though it should be completely transparent. If you are someone familiar with straight and premultiplied alpha, you might be interested to join the discussion in this issue I've opened on the hydra-synth repo.
.cs.elWith( f )
- Example:
osc(10,.1,2).rotate().hsv.hWith(x=>x.pixelate(16,32)).out()
- Alias:
.cs_el_with()
Inspired by TidalCycles xWith functions, these functions allow you to apply a transform only to a given element. The f
argument should be a function which receives a texture and returns a texture.
These are basically syntactic sugar for texture.cs.elFrom(cloneOfTexture.transform().el())
. This means that in order for these to work Hydra has to render the given texture twice, since its cloning it. So be very cautious about performance when using these.