int21h

Tvorba grafických efektů

V tomto kurzu se vám budu snažit vysvětlit některé jednodušší grafické efekty, které asi tak před 284 lety nemohly chybět v žádném demu. Možná se vám bude zdát, že jsou všechny až podezřele jednoduché. Většinou tomu tak opravdu je. Někdy je to ovšem tím, že by šly udělat lépe, ale já to neumím.


Sníh

A začneme hned nejjednodušším. Sníh se zadavá dokonce i jako úloha do knížek pro začínající programátory.
Myslím, že řešení by napadlo každého.
Tady je to moje:
Každá vločka má souřadnice x,y,z. Takových si uděláme pole.

o Nejdřív vločky nahážeme někde po obrazovce.
o Pak budem pro každou vločku opakovat:
o Smaž vločku
o Posuň souřadnici Y v závislosti na souřadnici Z (Z větší => rychlost menší)
o Náhodně posuň X souřadnici doleva nebo doprava
o Pokud je v obrazovce tak ji vykresli, jinak nastav Y na 1

Ach jo. Proč o tom vlastně píšu? Něčím jsem začít musel!

Toto je můj pokus:
snih.pas

Průlet hvězdokupou

Tímto krásným názvem obdarovali v Micro$oftu krásný spořič, který vás zavedl do světa plného hvězdiček nebo i okýnek.
Ale tento efekt je jeden z nejstarších.
Existuje víc způsobů návrhu (jako třeba přes vzorečky na kružnice a tak), ale snad chceme průlet, tak si uděláme rovnou 3d.

Praxe
Jeden bod bude vyjádřen třemi souřadnicemi x,y,z.
To se musí převést na nudnou 2d našeho monitoru.
x:=((x3d*512) div (512+z32))+(MAX_X div 2);
y:=((y3d*512) div (512+z3d))+(MAX_Y div 2);  

Algoritmus
Pro každou hvězdu:
o vymaž hvězdu
o zmenši Z
o zkontroluj, jestli není za limitem
o nakresli hvězdu

Tak a to je všechno. Jednoduchý ne? Přiložený příklad je napsaný v TP7, ale je portovatelný do jakéhokoli jazyka s podporou setcolor a putpixel.

hvezdy.pas

Oheň

U tohoto efektu je až neuvěřitelné jak je jednoduchý na vytvoření a záoveň náročný na výkon.
Opravdu jsem ještě neviděl jediný oheň, který by nebyl v Assembleru. Ono to totiž ani jinak nejde. Poslechněte si algoritmus a usuďte sami:

Pro každý bod spočítame:
barva:=([x-1,y]+[x,y]+[x+1,y]+[x,y+1]) div 4;  

Když si vezmete, že je na MCGA obrazovce 64000 bodů tak se to celkem protáhne
Samozřejmě že existuje víc způsobů, ale od žádného nečekejte rychlejší výsledky.
Optimalizace:
Opravdu nezbyde než asm. Jinak je taky výhodné nezapisovat rovnou na obrazovku, ale do nějakého bufferu, který se pak zkopíruje celý do videoramky.
Naštěstí moje schopnost v assembleru je tak primitivní, že jsem ho pochopí každý. A ještě jsem se ho snažil trochu popsat.

Paleta:
Tohle je taky kámen úrazu. Jak udělat paletu, aby se aspoň trochu podobala ohni.
Bohužel vypočítat to není tak lehké, pokud to vůbec jde.
Nejlepší řešení je udělat paletu v nějákém editoru (třeba v Gimpu) a uložit si ji do souboru. Pak už by stačilo ty barvy nějak načíst (nebo rovnou vložit do zdrojáku).
V mém příkladu se palety bohužel nedočkáte. (Kdo by se s tím štval).

A tady je:
Jinak tolik asm není můj styl, ale moje 486 se ráda ulívá.

ohen.pas

Plasma

Efekt Plasma ptaří mezi nejoblíbenější vůbec. Existuje mnoho způsobů jak něco podobného udělat. Dokonce tolik, že se začala plasma dělit na několik typů:

o Sinusoidní nebo Cosinusoidní Plasmy s elipsami
o Sinusoidní nebo Cosinusoidní Plasmy s vlnami
o Statické fraktálové plasmy s rotací palety

Fraktálové jsou zajímavé. Mají nejmenší náročnost, protože se tam pouze mění barvy palety, ale podklad je pořád stejný.
Akčnější jsou sin/cos plasmy. Já se budu zabývat tou první.

Matematická teorie

Sinusoida je snad každému známá. Budeme si ji ale muset převést do radiánů. Takže všechny sin v příkladě vrací v radiánech.

y = sin(x)

Ale v tomhle efektu se používá sčítání sinusoid.

y = 10*sin(x*4)+20*sin(x)+30*sin(x*4)

Tak. Ale teď do toho musíme započítat čas, aby se nám to pěkně pohybovalo
y:=10*sin(x*4+t)+
   20*sin(x+t*4)+
   30*sin(x*4+t);  

No ale tady je problém. Výsledek každého výpočtu nesmí být větší než 360. Tak co to vymodovat 360?
y = 10*sin((x*4+t) mod 360)+
    20*sin((x+t*4) mod 360)+
    30*sin((x*4+t) mod 360);  

Ale pokud se na to podíváte tak to není přesně to co bysme chtěli.
Dobře a teď přeskočíme několik listů najednou, protože to tady přestávám chápat:)
y = 10*sin((x*4+t) and 511)+
    20*sin((x+t*4) and 511)+
    30*sin((x*4+t) and 511);  

Podívejte se na příklad. Nejlíp to pochopíte, když skusíte změnit nějaký hodnoty a budete sledovat, co to dělá.
Možná přijdete i na pěknější variace.

Příklad:
Paleta je opravdu jen provizorní. Jak už jsem říkal, paleta je vždycky zádrhel. Ale v mnoha programech už pěkný palety jsou, tak si je můžete vystřihnout.
Jinak program je celkem rychlej i bez assembleru. Na mojí 486 běžěl 15.93 FPS, což není tak hrozný. Nepochybuju však, že by tomu asm pomohl.

plasma.pas
2006-11-30 | BOby
Reklamy:
„Mějte dobrou náladu. Dobrá nálada vaše problémy sice nevyřeší, ale naštve tolik lidí kolem, že stojí za to si ji užít.“ Jan Werich