<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zach Krall</title>
    <description>The latest articles on DEV Community by Zach Krall (@zachkrall).</description>
    <link>https://dev.to/zachkrall</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F388749%2F2bed2bd5-66c9-4974-a9df-0e463ff700d4.jpg</url>
      <title>DEV Community: Zach Krall</title>
      <link>https://dev.to/zachkrall</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zachkrall"/>
    <language>en</language>
    <item>
      <title>Getting started with generative art and Hydra</title>
      <dc:creator>Zach Krall</dc:creator>
      <pubDate>Fri, 15 Apr 2022 04:56:50 +0000</pubDate>
      <link>https://dev.to/zachkrall/getting-started-with-generative-art-and-hydra-2ikn</link>
      <guid>https://dev.to/zachkrall/getting-started-with-generative-art-and-hydra-2ikn</guid>
      <description>&lt;h1&gt;
  
  
  What is Hydra?
&lt;/h1&gt;

&lt;p&gt;Hydra is a JavaScript library for creating interactive visual art by &lt;a href="https://ojack.xyz/"&gt;Olivia Jack&lt;/a&gt;. The API was designed to function like an analog video synthesizer, where the output of one process is fed into the next one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ua5ikAjR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649994039812/eOdNvgGAF.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ua5ikAjR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649994039812/eOdNvgGAF.jpg" alt="Sandin Image Processor" width="880" height="660"&gt;&lt;/a&gt;Image: Sandin Image Processor, exhibited at School of the Art Institute of Chicago (SAIC), photographed by Rosa Menkman, &lt;a href="https://commons.wikimedia.org/wiki/File:Sandin%5C_Image%5C_Processor.jpg"&gt;https://commons.wikimedia.org/wiki/File:Sandin\_Image\_Processor.jpg&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hydra takes the resulting output and constructs a &lt;a href="https://www.khronos.org/opengl/wiki/Fragment_Shader"&gt;fragment shader&lt;/a&gt; that is rendered into a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas"&gt;&lt;/a&gt; element.&lt;/p&gt;

&lt;p&gt;This article will go over the three primary elements needed to make a hydra sketch: sources, modifiers, and outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To follow along with the code examples, you can use the hydra editor at &lt;a href="https://hydra.ojack.xyz/?code=JTBBJTIwJTBBJTIwJTJGJTJGJTIwVHlwZSUyMHNvbWUlMjBjb2RlJTIwb24lMjBhJTIwbmV3JTIwbGluZSUyMChzdWNoJTIwYXMlMjAlMjJvc2MoKS5vdXQoKSUyMiklMkMlMjBhbmQlMjBwcmVzcyUyMENUUkwlMkJzaGlmdCUyQmVudGVyJTBBJTBB"&gt;https://hydra.ojack.xyz/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;A source is a starting input for any hydra sketch. There are some predefined fragment shaders that are provided by hydra. We'll start by looking at &lt;code&gt;osc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An oscillator takes the &lt;code&gt;x&lt;/code&gt; coordinate of the screen and passes it through a sine wave, essentially moving continuously between black (&lt;code&gt;vec3(0.0,0.0,0.0)&lt;/code&gt;) and white (&lt;code&gt;vec3(1.0,1.0,1.0)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vM_4Nqgf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649995698279/ouRtl2zAZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vM_4Nqgf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649995698279/ouRtl2zAZ.png" alt="hydra-2022-4-15-0.5.42.png" width="880" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To render the oscillator, we attach the &lt;code&gt;out&lt;/code&gt; function to our source function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;osc().out()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;osc&lt;/code&gt; function takes three parameters: frequency, speed, and offset.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frequency affects how long a full cycle takes for the sine wave or essentially, how many bands appear on the screen (default: 60)&lt;/li&gt;
&lt;li&gt;speed affects how quickly the oscillator moves to the left (default: 1.0)&lt;/li&gt;
&lt;li&gt;offset affects the distance between and red, green, and blue channels (default: 0)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iS3cA5Ih--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649996490150/yHW7b6NAL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iS3cA5Ih--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649996490150/yHW7b6NAL.png" alt="hydra-2022-4-15-0.21.20.png" width="880" height="682"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;osc(10, 0.1, 0.3).out()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try seeing what happens if you use: &lt;code&gt;gradient&lt;/code&gt;, &lt;code&gt;noise&lt;/code&gt;, &lt;code&gt;shape&lt;/code&gt;, &lt;code&gt;solid&lt;/code&gt;, or &lt;code&gt;voronoi&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Modifiers
&lt;/h2&gt;

&lt;p&gt;Modifiers take the pixel data from a previous process, manipulates it, and returns a new function that you can either pass to another modifier, or an output channel.&lt;/p&gt;

&lt;p&gt;For example, we could take our oscillator and rotate it 90 degrees. Since we're working with WebGL, we'll need to convert degrees into radians.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kC0LHFU8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649996832065/TRdUi9RNR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kC0LHFU8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649996832065/TRdUi9RNR.png" alt="hydra-2022-4-15-0.26.31.png" width="880" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An easy way to set this up is to use &lt;code&gt;&amp;lt;DEGREES&amp;gt; * Math.PI / 180&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;osc(10, 0.1, 0.3).rotate(90 * Math.PI / 180).out()
// or
osc(10, 0.1, 0.3).rotate(Math.PI * 0.5).out()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any parameter can be defined as a function or array, so we could change our rotation over time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;osc(10, 0.1, 0.3)
.rotate((args) =&amp;gt; {
   const d = args.time * 0.1
   return Math.PI * d
})
.out()


const r1 = Math.PI * 0.5
const r2 = Math.PI * 0.25

osc(10, 0.1, 0.3)
.rotate([r1, r2])
.out()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also increase the color saturation of our shader with &lt;code&gt;saturate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WTYditfj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649997464480/oslVKv-e_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WTYditfj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649997464480/oslVKv-e_.png" alt="hydra-2022-4-15-0.37.37.png" width="880" height="682"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;osc(10, 0.1, 0.3).rotate(Math.PI * 0.5).saturate(5).out()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also use operators like &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;blend&lt;/code&gt;, &lt;code&gt;mult&lt;/code&gt; to mix layers together.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LSipG0aU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649997820727/_nDYHW03I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LSipG0aU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649997820727/_nDYHW03I.png" alt="hydra-2022-4-15-0.43.30.png" width="880" height="682"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const triangle = shape(3, 0.4).scrollY(0.07).rotate(Math.PI)

osc(10, 0.1, 0.3)
.rotate(Math.PI * 0.5)
.saturate(5)
.mult(triangle)
.out()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Output
&lt;/h2&gt;

&lt;p&gt;Hydra has four possible output buffers. By default &lt;code&gt;out&lt;/code&gt; send the shader to the first buffer or &lt;code&gt;o0&lt;/code&gt;. We can observe all four buffers by using the &lt;code&gt;render&lt;/code&gt; function without any parameters&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dbNY3HJq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649997628681/7quoufFGb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dbNY3HJq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1649997628681/7quoufFGb.png" alt="hydra-2022-4-15-0.40.23.png" width="880" height="682"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;osc().out(o0)
noise().out(o1)
shape().out(o2)
voronoi().out(o3)

render()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can switch to displaying a single buffer by passing in the buffer name as a parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;render(o2)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Experiment!
&lt;/h2&gt;

&lt;p&gt;Now that you're familiar with hydra's syntax including sources, modifiers, and output buffers, you can start exploring with chaining functions together in different ways to make some fun visuals!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hydra Github repository: &lt;a href="https://github.com/hydra-synth/hydra"&gt;https://github.com/hydra-synth/hydra&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;All hydra functions: &lt;a href="https://github.com/hydra-synth/hydra/blob/main/docs/funcs.md"&gt;https://github.com/hydra-synth/hydra/blob/main/docs/funcs.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Introduction to Hydra workshop at NYU, February 2019: &lt;a href="https://www.slideshare.net/ZachKrall/hydra-workshop-nyu-live-code-lab-feb-2019"&gt;https://www.slideshare.net/ZachKrall/hydra-workshop-nyu-live-code-lab-feb-2019&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
