Psychedelické vlny

Precvičíme si dvojitý cyklus a popri tom sa naučíme lepšie pracovať s farbami a používať animáciu vo výrazoch. Výsledkom bude niečo takéto dúhové:

Základný program

Začneme so štandardným setup a draw skečom v ktorom pomocou dvojitého cyklu vytvoríme mriežku o veľkosti d a do každého políčka mriežky vykreslíme krúžok.

Pomôžeme si premennými riadkov a stlpcov, do ktorých vypočítame, koľko riadkov a stĺpcov potrebujeme na základe veľkosti okna a veľkosti políčka d:

float d = 10;
int riadkov, stlpcov;

void setup()
{
  size(400,400);
  background(0);
  riadkov = height/d;
  stlpcov = width/d;
}

void draw()
{
  background(0);
}

Krúžky v mriežke

V dvojitom cykle prejdeme všetky riadky a všetky stĺpce:

void draw()
{
  background(0);
  for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
 
    }
  }
}

Vo vnútri cyklu nám premenná r označuje, v ktorom riadku sa práve nachádzame a premenná s v ktorom stĺpci. Keďže veľkosť políčka je d pixelov, tak pixelové súradnice políčok v mriežke budú d*s a d*r. Skúsme na ne vykresliť krúžky o veľkosti d:

  for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
       circle(d*s, d*r, d);
    }
  }

Krúžky sú posunuté a to nechceme:

Parametre príkazu circle označujú stred krúžku. Ten chceme mať v strede políčka v mriežke. Ale súradnice d*s a d*r nie sú stredom políčka. Sú jeho ľavým horným rohom. Tak ich ešte musíme posunúť o polovicu veľkosti políčka, o d/2 v oboch súradniciach:

  for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
       circle(d*s + d/2, d*r + d/2, d);
    }
  }

Teraz už sú krúžky na mieste:

Skúsme im ešte každému priradiť náhodnú RGB farbu:

       fill(random(256), random(256), random(256));
       circle(d*s + d/2, d*r + d/2, d);

Farba v režime HSB

Aby sme vedeli narábať nejak rozumne s farbou, potrebujeme mať kontrolu nad hodnotami, cez ktoré farbu nastavujeme. Štandardne hodnoty v príkazoch ako fill a stroke predstavujú RGB zložky farby. Napríklad fill(255, 255, 0) je žltá farba.

Problém je, že v takomto režime by sa nám veľmi ťažko vyrábal dúhový farebný, aký chceme. Všimnite si napríklad, že na obrázku vyššie sú okrem jasných farieb aj tmavé aj bledé aj pastelové aj sýte. Chceli by sme mať len jasné farby, ale nevieme to cez RGB nastaviť.

Pomôžeme si tým, že prepneme skeč do režimu HSB. Takto:

void setup()
{
  size(400,400);
  background(0);
  riadkov = height/d;
  stlpcov = width/d;
  colorMode(HSB);
}

V režime HSB trojica parametrov vo fill alebo stroke nepredstavuje RGB zložky farby ale HSB zložky:

  • H ako hue je farebný tón (či je farba červená alebo oranžová alebo tyrkysová a pod.)

  • S ako saturation je sýtosť farby (či je červená farba sýta alebo mdlá)

  • B ako brightness je svetlosť farby (či je sýta červená farba svetlá alebo tmavá)

Vďaka tomu máme kontrolu nad tým, aké sýte, aké svetlé sú farby a keď zafixujeme svetlosť a sýtosť na 255 a ponecháme náhodný len prvý parameter - farebný tón - dostaneme jasné farby všetky:

       fill(random(256), 255, 255);
       circle(d*s + d/2, d*r + d/2, d);

Farba podľa polohy

Zatiaľ sme len provizórne nastavili farbu ako náhodnú. Ak chceme robiť nejaké farebné prechody či vlny, musí farba závisieť od polohy. Polohu nám určujú premenné r a s, tie hovoria v ktorom riadku a stĺpci som.

Vyrobme si premennú h, ktorou budeme určovať farebný tón a vnútri cyklu ju nastavme na hodnotu premennej s:

  for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
       float h = s;
       fill(h, 255, 255);
       circle(d*s + d/2, d*r + d/2, d);
    }
  }

Ak chceme farebný prechod zhustiť, tak len vynásobíme s , napríklad 5-krát:

 for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
       float h = 5*s;
       fill(h, 255, 255);
       circle(d*s + d/2, d*r + d/2, d);
    }
  }

Vyskúšajte do h priradiť rôzne iné výrazy okrem 5*s. Skúste napríklad s*s alebo r*s alebo r+s ... pohrajte sa.

Farba podľa času

Keď do výrazu na výpočet h pridáme nejakú hodnotu, ktorá sa mení v čase, získame animáciu.

Vytvorme si globálnu premennú t :

float d = 10;
int riadkov, stlpcov;
float t = 0;

Vo vnútri v draw ju budeme zvyšovať o 1 a rovno ju aj zapojíme do výpočtu farby h:

void draw()
{ 
  background(0); 
  for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
       float h = 5*s + t;
       fill(h, 255, 255);
       circle(d*s + d/2, d*r + d/2, d);
    }
  }
  t = t + 1;
}

Vyskúšajte skeč teraz, farebná vlna sa bude hýbať sprava doľava:

Akurát po istom čase ostane kompletne červená:

To je preto, že hodnota výrazu h = 5*s + t vystúpala nad 255, a to je mimo rozsah parametra H v HSB. Môžeme ale zaloopovať túto hodnotu tak, aby skočila naspať na 0 ak vystúpi nad 255. Konkrétne takto:

Operátor % zvaný aj modulo

Pomôže nám špeciálna matematická operácia - zvyšok po delení. Volá sa aj modulo a má značku %. Použijeme ho takto:

       float h = (5*s + t) % 256;

Vo výsledky tak po modrej, fialovej a červenej neostáva konštantná červená ako predtým, ale začína sa odznova s červenou, oranžovou, žltou a tak stále dokola.

Ako funguje % ?

Operátor modulo (%) robí z hodnôt zvyšky po celočíselnom delení.

Napríklad 11 % 4 je 3. Lebo 11 deleno 4 sú 2 celé čísla a zvyšok zostane 3. Alebo 102 % 10 je 2. Lebo 102 deleno 10 je 10 celých a zvyšok zostane 2. Alebo 256 % 256 je 0. Lebo 256 deleno 256 je 1 a zvyšok zostane 0. Alebo 17 % 256 je 17. Lebo 17 deleno 256 je 0 celých a zvyšok je 17.

Takže s hodnotami 0...255 neurobí operátor nič, nechá ich ako sú. A vyššie hodnoty oseká do intervalu 0..255. Z 256 urobí 0, z 257 urobí 1 a tak ďalej.

Animácia veľkosti bodov

Aby sme posilnili psychedelično, budeme meniť aj veľkosti bodov. Vytvorte v cykle premennú v a nastavte ju na náhodnú hodnotu od 0 po d. Premennú v použijeme ako veľkosť v príkaze circle.

  for (int r = 0; r < riadkov; r++)
  {
    for (int s = 0; s < stlpcov; s++)
    {
       float h = (5*s + t) % 256;
       float v = random(d);
       fill(h, 255, 255);
       circle(d*s + d/2, d*r + d/2, v);
    }
  }

Výsledkom je náhodné dúhové zrnenie:

To je samozrejme len dočasný stav, kým vyrobíme pre veľkosť tiež nejaký pekný výraz, ktorý bude veľkosti animovať.

Funkcia sin()

Druhé matematické kúzlo, s ktorým si pomôžeme, je funkcia sínus, alias sin(). Tá vytvára z po sebe idúcich hodnôt rastúcu a klesajúcu a rastúcu a klesajúcu postupnosť:

Keď teda do nej budeme dávať ako parameter časovú premennú t, bude rásť a klesať a rásť a klesať a tak stále dokola. Skúsme takto:

       float v = sin(t);

Výsledok je nič:

To preto, že funkcia sin() generuje hodnoty len v rozsahu od -1 po +1. Tým pádom sa nám síce krúžky vykresľujú, ale sú veľké najviac 1 pixel. Čo v spojení s tým, že sme nevypli noStroke() znamená, že sú to 1px veľké krúžky s čiernym okrajom na čiernom pozadí.

Musíme sínus zväčšiť:

       float v = d*sin(t);

Teraz už budú krúžky viditeľné, lebo sú v rozsahu nie -1 po 1, ale v rozsahu od -d po +d.

Akurát blikajú ako zbesilé. Tak ešte musíme sínus spomaliť. Takto:

       float v = d*sin(t/20);

Tým bude kmitanie 20-krát pomalšie:

Tento obrázok nekmitá, lebo to nie je GIF. Chyba nie je vo vašom prijímači.

Vlny

Všetky body kmitajú so svojou veľkosťou naraz, synchrónne. To preto, že veľkosť počítame sínusom len z premennej t. A tú majú všetky krúžky spoločnú.

Aby sme vyrobili nejaké priestorové vlny, musíme do sínusu zamontovať nejak aj r a s. Skúsme napríklad takto:

       float v = d*sin((r*s - t/5)/13);

To je celkom zaujímavý obrazec:

Ako som prišiel na taký komplikovaný vzorec? Jednoducho: skúšaním, experimentovaním.

A aby sme vyrobili ešte psychedelickejšiu farebnú vlnu, poexperimentujeme aj s výrazom pre farbu h:

       float h = (8000 + 2*t-5*r*s)%256;

Elegancia takéhoto programu je v tom, že keď napríklad zmeníme veľkosť mriežky:

int d = 20;

A doladíme niektoré konštanty vo vzorcoch:

       float v = d*sin((r*s - t/5)/6);

Tak dostávame niečo trochu iné, ale podobné:

Máme tak vytvorenú základnú platformu pre experimentovanie s veľkosťami, farbami, časom a budú nám vznikať najrôznejšie generatívne obrazce. Nemusíme rozumieť tomu, čo presne ktoré číslo robí, ale metódou pokus-omyl dokážeme intuitívne pochopiť, ktoré číslo rozťahuje ktorú vizuálnu vlastnosť.

Tu je finálny skeč:

Last updated