Plazma
Vizuálny efekt plazmy je jeden zo základných cvičení, ktoré pochádza ešte z dávnych ér demoscény (Wikipedia: Plasma effect).

Základný program
Budeme vychádzať z podobného základu ako pri tutoriáli Psychedelické vlny. Ak ste tento tutoriál nerobili, tak si urobte najprv ten.
Podobne ako v tom tutoriáli, budeme aj tu používať dvojitý cyklus, ktorý prechádza mriežku na obrazovke políčko po políčku. Akurát v každom políčku vykreslíme štvorček a nie krúžok. A ešte si nastavíme HSB farebný mód hneď na začiatku, lebo to už poznáme a nebudeme sa tomu ďalej venovať.
float d = 20;
int riadkov,stlpcov;
void setup()
{
size(800,400);
riadkov = int(height/d);
stlpcov = int(width/d);
colorMode(HSB);
}
void draw()
{
for (int r = 0; r < riadkov; r++)
{
for (int s = 0; s < stlpcov; s++)
{
square(s*d, r*d, d);
}
}
}

Príkaz map()
map()
Prvým základným bodom plazma efektu je nastavenie farby políčka podľa jeho polohy. Napríklad takto by vyzeralo, keby sme nastavili farbu podľa stĺpca s
:
void draw()
{
for (int r = 0; r < riadkov; r++)
{
for (int s = 0; s < stlpcov; s++)
{
fill(s, 255, 255);
square(s*d, r*d, d);
}
}
}

U vás tento farebný prechod môže vyzerať rôzne, podľa toho, koľko máte stĺpcov. Vždy bude síce začínať na červenej farbe (s = 0
) ale skonči to pri inej farbe, ak máte iný počet stĺpcov.
Ak by sme chceli, aby to vždy obsiahlo celú farebnú škálu od 0
po 255
, použijeme príkaz map
.
Tento príkaz zoberie hodnotu z nejakého intervalu, v našom prípade hodnotu s
z intervalu 0
až stlpcov
. A prepočíta ju na hodnotu z iného intervalu, v našom prípade 0
až 255
. Takto:
fill( map(s, 0, stlpcov, 0, 255) , 255, 255);
Namiesto samotného s
sme toto s
premapovali na interval 0
až 255
a tým máme zabezpečené, že nech je stĺpcov hocikoľko, vždy bude farba začínať na 0
a prejde celé spektrum až po 255
:

Vzdialenosť a príkaz dist()
dist()
Druhým základným bodom plazma efektu je nastavenie farby podľa vzdialenosti od nejakého bodu (alebo bodov). Teraz máme farbu nastavenú len podľa horizontálnej súradnice s
. Doplníme si nejaký stred a budeme farbu nastavovať podľa vzdialenosti od neho.
Vytvorte súradnice cx
, cy
a nastavte ich na stred obrazovky:
float d = 20;
int riadkov,stlpcov;
float cx, cy;
void setup()
{
size(800,400);
riadkov = int(height/d);
stlpcov = int(width/d);
colorMode(HSB);
cx = width/2;
cy = height/2;
}
Vo vnútornom cykle si vypočítame x
,y
súradnice práve vykresľovaného štvorčeka, lebo z tých potom budeme vypočítavať, ako ďaleko na obrazovke je od cx
, cy
:
for (int r = 0; r < riadkov; r++)
{
for (int s = 0; s < stlpcov; s++)
{
float x = s*d;
float y = r*d;
fill( map(s, 0, stlpcov, 0, 255) , 255, 255);
square(x, y, d);
}
}
Vzdialenosť medzi bodom x
,y
a bodom cx
,cy
nám vypočíta funkcia dist()
, uložíme si vypočítanú vzdialenosť do premennej v
:
float x = s*d;
float y = r*d;
float v = dist(x, y, cx, cy);
fill( map(s, 0, stlpcov, 0, 255) , 255, 255);
square(x, y, d);
A namiesto súradnice s
použijeme do výpočtu farby túto novú hodnotu - vzdialenosť v
:
float x = s*d;
float y = r*d;
float v = dist(x, y, cx, cy);
fill( map(v, 0, stlpcov, 0, 255) , 255, 255);
square(x, y, d);
Akurát, že obrázok je dosť zdecimovaný:

To je preto, že v príkaze map
, kde sme pôvodne mapovali s
na farbu, tak teraz mapujeme vzdialenosť v
. Ale toto v
už nie je z intervalu 0
až stlpcov
. Musíme teda upraviť aj interval z ktorého mapujeme. Najmenšia vzdialenosť je 0
, to zostáva, ale maximálnu vzdialenosť nepoznáme. Použime napríklad width/2
, lebo to je vzdialenosť od stredu obrazovky po jej kraj.
fill( map(v, 0, width/2, 0, 255) , 255, 255);

Animácia a príkaz sin()
sin()
Treťou časťou je animácia. Pridajme do programu počítadlo času:
float d = 20;
int riadkov,stlpcov;
float cx, cy;
float t = 0;
A začleňme ho do výpočtu farby:
void draw()
{
for (int r = 0; r < riadkov; r++)
{
for (int s = 0; s < stlpcov; s++)
{
float x = s*d;
float y = r*d;
float v = dist(x, y, cx, cy);
fill( map(v + t, 0, width/2, 0, 255) , 255, 255);
square(x, y, d);
}
}
t = t + 1;
}
Animácia už beží, ale po chvíľke farby zdegenerujú do čisto červenej:

To preto, že keď rastie t
, tak časom vyrastie príliš vysoko a farby s hodnotou nad 255 sú už konštantne červené.
Ak chceme, aby sa niečo v čase periodicky opakovalo, tak použijeme funkciu sínus. Ako bude čas rásť, tak funkcii sínus je to jedno, tá bude stále produkovať hodnoty od -1 po 1 a tak dokola. Nikdy nevylezie do nekontrolovateľných výšok.
Akurát budeme musieť pozmeniť aj interval z ktorého mapujeme farby. Teraz je to 0 až width/2. Po použití sínusu to bude -1 až 1:
fill( map( sin(v + t), -1, 1, 0, 255) , 255, 255);
Teraz sa už farby periodicky menia, ale zase strašne divoko:

Potrebujeme to, čo je vnútri sínusu spomaliť, tak vydelíme aj v
aj t
nejakými číslami:
fill( map( sin(v/100 + t/50), -1, 1, 0, 255) , 255, 255);

Plazma s viacerými stredmi
Plazma len s jedným stredom je nudná. Pridáme do vzdialenosti aj druhý stred a bude to pozícia myši:
float v = dist(x, y, cx, cy) + dist(x,y,mouseX,mouseY);

Prípadne aj tretí stred, na náhodnú pozíciu:
float d = 20;
int riadkov,stlpcov;
float cx, cy;
float dx, dy;
float t = 0;
void setup()
{
size(800,400);
riadkov = int(height/d);
stlpcov = int(width/d);
colorMode(HSB);
cx = width/2;
cy = height/2;
dx = random(width);
dy = random(height);
}
A ešte upravíme výpočet vzdialenosti:
float v = dist(x, y, cx, cy) + dist(x, y, mouseX, mouseY) + dist(x, y, dx, dy);

Vyladenie farieb
Obvykle sa plazma nerobí v dúhových farbách, ale v nejakej kombinácii červenej, žltej, oranžovej. Toto vieme upraviť keď zúžime cieľový interval mapovania z 0
až 255
na 0
až 40
:
fill( map( sin(v/100 + t/50), -1, 1, 0, 40), 255, 255);

Tu je finálny skeč:
Modifikácie
Zmeňte farebnú škálu tak, aby namiesto červenej, oranžovej až žltej bola zelená, tyrkysová až modrá.
Rozhýbte body
cx
,cy
adx
,dy
nejakým pohybom. Môžu sa odrážať od stien, alebo sa môžu loopovať cez okraje obrazovky
Last updated