Stíny a světla trochu jinak - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



Delphi

Stíny a světla trochu jinak

pixel_light_and_shadow

17. června 2002, 00.00 | Chcete ve své hře používat světla a stíny a vadí vám že funkce DelphiX jsou moc pomalé? V tomto článku si ukážeme že to jde i jinak a hlavně rychleji.

Po dlouhé době je zde další článek o programování her v DelphiX. Tedy, na co se můžete těšit (nebo naopak ;)) ? Jak jste si už možná u mě zvykli, bude i tento článek především o grafice, konkrétně probereme tvorbu stínů a světel přes pixely a nikoliv žádné složité funkce. Hurá do toho ;)

Tvorba stínů a světel je odvěký problém. Na jednu stranu vypadají hezky, na druhou dost zatěžují procesor. Konkrétně teď mluvím o kreslení v DelphiX přes funkce DrawSub či DrawAdd. Každý jistě zkusil že stačí jeden větší objekt nakreslit touto funkcí, a program spadne na 4FPS (v lepším případě). Dnes si proto ukážeme jednu z dalších možností, která je sice již trochu starší, ale vypadá pořád dobře.

Abychom nakreslili stím či světlo, použijeme malý trik. Lidský zrak lze celkem snadno oklamat, navíc v době velkých monitorů a ještě větších rozlišení. Stačí vyplnit každý druhý pixel černou resp. bílou barvou a stín resp. světlo je na světě. To je celé tajemství dnešního článku. Ale samozřejmě ještě nekončíme, nyní si vše vyzkoušíme v praxi.

Podívejte se pozorně na následující obrázek, pravý čtverec je kreslený přes DrawSub, levý je pouze průhledný černobílý obrázek, vyplněný mřížkou. Efekt je přibližně stejný, čas na vykreslení se však rapidně mění. Bohužel čím větší rozlišení, tím je víc vidět že jsme použili tento trik, tudíž moc nedoporučuji používat toto pokud děláte hru přes fullscreen např. pro 640*480px. Zde je slibovaný obrázek:


Základy máme, vrhneme se na program. Chtěl jsem říci na grafiku. O co jednodušší je kreslení v Delphi, o to složitější je tvorba takových obrázků. Ale ne zas tak složitá, aby to nezvládl každý po důkladném přečtení tohoto článku ;)
V našem demo programu nezůstaneme u statických obrázků, ale přejdeme rovnou k animaci, kdy se nad pozadím bude vykreslovat otáčející se krychle (později i hvězda). Tyto obrazce budou kresleny pouze stíny a světly, a aby měly trochu tvar bude kolem nich i černý obrys. Pokud si nedovedete představit k čemu chceme dospět, podívejte se na konec článku na screenshot nebo na tento obrázek:


Tvorba grafiky

Tvorba animace v 3D Studiu MAX

Začneme tedy s grafikou. Vzhledem ke skutečnosti že krychle zabírá tři dimenze zvolíme na začátek program 3D studio MAX (alespoň základní znalost se určitě bude hodit). Po pár sekundách či minutách se spustí a rozprostře na ploše svoje okno. Zvolíme záložku Objects, klikneme na Box Objects (ikonka krychle) a stylem táhni a pusť nakreslíme v jakémkoliv pohledu krychli. To samé uděláme ještě jednou, ovšem s tím rozdílem že druhá krychle bude ve skutečnosti zem, na kterou dopadne stín, a proto se podle toho zařídíme (tedy aby hlavně byla pod první, a trochu větší). Dále klikneme na záložku Lights&Cameras \ Omni Light. Toto světlo umístíme do scény nad obě krychle. Jak scéna vypadá můžete vidět zde:


Nějaké parametry nás nemusí moc zajímat, hlavní je nastavit u světla parametr cast shadows, abychom měli stín:


Dále nastavíme pozadí scény na bílou - Rendering \ Environment: Background - Color. Přepneme do pohledu Perspective a zkušebně si vyrenderujeme scénu (Rendering \ Render \ Render). Pokud výsledek vypadá nějak takto, je vše v pořádku a můžeme pokračovat (hlavní je aby stěny kdychle byly dostatečně kontrastní a neměly moc podobnou barvu):


Pomalu ale jistě se dostáváme k animaci. Než k ní ale přiskočíme, musíme upravit jednu duležitou věc - střed kdychle. Chceme totiž aby se otáčela okolo svého středu, ale 3DS MAX nedělá střed kdychle ve středu krychle ;) Pomůžeme si na záložce Hierarchy \ Affect Pivot Only:


a posuneme Pivot na střed:


Tím bychom toto měli a pustíme se do animace. Vespod posuneme časový posuvník na pozici 10, klikneme na velké nepřehlédnutelné tlačítko Animate, dále na krychli, potom na ikonku Select and Rotate, ještě jednou na ní klikneme, ale pravým tlačítkem, a do okna které se nám objeví napíšeme u Z osy 90. Znovu klikneme na tlačítko Animate, aby přestalo svítit červeně a jsme hotovi. Nyní už jen animaci vyrenderovat. Ještě pro jistotu takto vypadá časová osa, červeně jsou označeny klíčové snímky (keyframes):


Na řadě je render. Klikneme na Rendering \ Render, do okna zadáme velikost na 100*200px, Time Output nastavíme na Range: from 0 to 10, a Render Output na Save File a vybereme složku do které si animaci uložíme. Použijte soubory bmp, na barevné hloubce nezáleží. Po pár minutách je animace na světě. Můžeme s klidným srdcem scénu uložit, zavřít maxko a pustit se do další práce. A co bude následovat ?

Slepení obrázku v programu Glue-IT

Pro další práci potřebujeme jednotlivé obrázky animace slepit k sobě. Jedním ze způsobů je otevřít Malovaní a kopírovat a vkládat až do zbláznění, další způsob je použít program Glue-IT který toto udělá za vás ;)
Stáhnout si jej můžete ZDE Stáhněte si tedy tento program na disk a spusťte jej. Klikněte na tlačítko Add /images, a v nově otevřeném okně vyberte všechny obrázky animace. Dejte pozor aby šly za sebou. Klikněte na tlačítko Glue-It a nahoře si zkontrolujte, zda-li je vše v pořádku. Pokud ano, klikněte na Save Glued a výsledný obrázek uložte. Tím naše práce s tímto programem skončila. Výsledek bude vypadat nějak takto (klikněte pro celý obrázek):


A následovat bude...

Konečná úprava grafiky v Photoshopu

Spustíme prohoshop, otevřeme obrázek a dáme se do práce. Naši vrstvu zkopírujeme, a tuto novou vrstvu odbarvíme - Image \ Adjust \ Desaturate. Následeně potřebujeme jen pár odstínů, takže převedeme vrstvu jen na určitý pořet barev - Image \ Adjust \ Posterize. Hodnotu zadáme 4 a potvrdíme. Výsledek vypadá přibližně takto:


(Poznámka: pokud se vám slily boční stěny do jedné barvy, musíte trochu zvětšit kontrast.)
Teď ale máme ve vrstvě pouze tři barvy, takže barva pozadí je stejná jako barva horní stěny krychle. to samozřejmě nechceme, takže přepneme zpět do první vrsty a kouzelnou hůlkou vybereme bílé okolí. Nezapomeňte vypnout Antialiasing, toleranci dejte přibližně na 10. Výběr máme, přepneme do druhé vrstvy. Nyní už jen stačí stisknout tlačítko Delete a je hotovo. Abychom viděli že opravdu je vrstva průhledná, vyplníme pozadí svítivě zelenou (RGB: 0,255,0). Zatím vypadá náš obrázek takto:


Nyní si v nové vrstvě definujeme dva vzorky které budeme používavt pro výplň kostky. Jeden pro stín, druhý pro světlo. (Vzorek se definuje způsobem Edit \ Define Pattern):


Ještě než začneme s výplní, musíme si nastavit barvu stínu pod krychlí na černou.
Pokračujeme již slíbenou výplní. Vezmeme kouzelnou hůlku, nastavíme toleranci na 0, a vypneme Contiguous, a klikneme do černé oblasti krychle. Zvolíme Edit \ Fill > Use: Pattern, vyberem vzorek stínu a potvrdíme OK. Takto to uděláme i se světlou stranou (použijeme vzorek světla) i s vrchní (použijeme bílou barvu). Zapomněl jsem napsat že vše děláme do nových vrstev, abychom to mohli dále ještě trochu upravit. Například pokud při výběru vybereme i samostatné pixely které očividně vyplnit nechceme (různé hrany které nejsou u stěny), buďto je gumou smažeme nebo použijeme malý trik, nejprve selekci o jeden pixel změnšíme, a následně o jeden pixel zvětšíme. Tvar se sice trochu změní, ovšem jen nepatrně a samostatné pixely jsou pryč.
Nakonec vytvoříme výběr z prvního obrázku, dáme Select \ Invers, trochu jej zvětšíme - Select \ Modify \ Expand - 1px - OK a novou vrstvu vyplníme černou barvou (obrys). Tím jsme skoro hotovi.
Poslední věc bude odseknutí poslední části animace, protože pokud se pozorně podíváte na obrázek, první a poslední části jsou naprosto shodné. Zvolíme tedy Image \ Canvas size a místo 1100 px šířky zadáme 1000px. Tím jsme s obrázkem hotovi, zde můžete vidět výsledek (opět klikněte pro zvětšení).


Hodit se bude i nějaké to pozadí, takže tady je:


Další 3D objekty

Pokud jste zvládli udělat takovouto krychli, není už žádný větší problém udělat podobným způsobem jakýkoliv další 3D objekt. Důležité je aby nebyl příliš kulatý, jelikož by se těžko stínoval. To nám ovšem zůstává plno dalších objektů, jako je například jeden ze základních objektů MAXka - hvězda. Je udělána úplně stejným způsobem. Výsledek vidíte zde (klikněte pro zvětšení):


Tím jsme s grafikou skončili (konečně ;)) a můžeme se pustit do...

Programování

Princip našeho programu bude jednoduchý - to co jsme si pracně nakreslili si teď jednoduše, a hlavně rychle nakreslíme. Navíc si budeme moci vybrat co chceme zobrazit a pokud klikneme na formulář, posune se objekt do strany (demonstrace že všude vypadá hezky ;). Vytvoříme nový projekt, na form dáme DXTimer, DXImageList a DXDraw komponenty. U DXImageListu přidáme tři položky - pozadí, hvězdu a krychli. U pozadí vypneme průhlednost, u ostatních zapneme. Dále také u posledních dvou nastavíme PatternHeight na 200 a PatternWidth na 100 pixelů. Na formulář ještě přidáme jeden SpeedButton pro změnu obrázku. To je z komponent vše, nyní si ještě ukážeme zdrojové kódy.

Nejdříve začneme proměnnými, podle komentáře je snad jasné co k čemu slouží:


    i,j:integer;  // fáze zobrazení kostky / hvězdy
    xpos:real;    // x-ová pozice
    xvel:real;    // x-ová rychlost
    obj:integer;  // co zobrazit


Následuje procedura Form.OnCreate, ve které si všechny proměnné nastavíme:


procedure TForm1.FormCreate(Sender: TObject);
begin
 i:=0;
 j:=0;

 xpos:=330;
 xvel:=0;

 obj:=0;

 randomize;
end;


Dále pokračujeme procedurou DXTimer.OnTimer:


procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
// kterou část animace u kostky / hvězdy zobrazit
i:=i+1;
j:=j+1;
if i = 10 then i:=0;
if j = 15 then j:=0;

// upravíme x-ovou pozici podle rychlosti..
xpos:=xpos+xvel;
// a změnšíme rychlost..
xvel:=xvel * 0.95;

// nakreslíme pozadí
DXimageList1.Items[0].Draw(DXDraw1.Surface,0,0,0);
// a jeden z objektů..
if obj = 1 then DXimageList1.Items[2].Draw
(DXDraw1.Surface,Trunc(xpos),80,i)
else if obj = 0 then DXimageList1.Items[1].Draw
(DXDraw1.Surface,Trunc(xpos),80,i);

// a to je vše ;)
dxdraw1.flip;
end;


Přidáme proceduru DXDraw.OnClick:


procedure TForm1.DXDraw1Click(Sender: TObject);
begin
 // pokud je nalevo od středu - dáme plusovou rychlost
 // aby objekt letěl doprava, pokud je napravo, dáme
 // rychlost zápornou... aby se nedostal z plochy...
 if xpos < 200 then Xvel:=Random(11)+3 else
 Xvel:=-(Random(11)+3);
end;


A vše ukončíme procedurou SpeedButton.OnClick:


procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
 // změníme zobrazovaný objekt
 if obj = 0 then
  begin
   obj:=1;
   SpeedButton1.Caption:='star';
  end
 else if obj = 1 then
  begin
   obj:=0;
   SpeedButton1.Caption:='cube';
  end;
end;


Tím jsme u konce i se zdrojákama, takže nezbývá nic jiného než program spustit, a sledovat jak hezky si objekty létají ;)
Takže tady máte screenshot, pod ním odkazy na všechny soubory které si můžet stáhnout... Využití si už určitě najdete všichni sami...


Download

ZDE si můžete stáhnout dnes vytvořený program a jeho zdrojáky (454 kB)
ZDE si můžete stáhnout oba soubory photoshopu (267 kB)
ZDE si můžete stáhnout oba soubory 3D studia MAX (30 kB)

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Delphi  

 » Rubriky  » Windows  

 

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: