Direct 3D - Hmla
Hmlu môžete najčastejšie nájsť v hrách s obrovskými a otvorenými priestormi, kde sa na konci viditeľnosti, ktorá sa nastavuje pri vytváraní matice projekcie, používa hmla. Koniec scény potom už nie je tak násilne ukončený, pretože vyzerá oveľa prirodzenejšie. Hmla dotvára atmosféru, môže dokonca zakryť aj niektoré chyby.
Teória
Ako bude objekt ovplyvnený hmlou, udáva jeho vzdialenosť od kamery resp. hĺbka v scéne. Čím je objekt vzdialenejší, tým viac je jeho pôvodná farba miešaná s farbou hmly. Nakoniec je celý objekt sfarbený touto farbou. Vytvára sa tak ilúzia, že sa objekt stráca v hmle.
Direct3D používa dva typy hmly: Pixel fog (niekedy sa nazýva table fog) a Vertex fog - každý so svojimi špecifickými vlastnosťami. Hlavný rozdiel medzi nimi je v tom, kto sa stará o prepočítavanie hmly. Pixel fog je podporovaný v driveroch grafickej karty. Pred tým, ako má byť každý pixel zobrazený na obrazovke je jeho výsledná farba prepočítaná podľa fog faktoru. Vertex fog je obsiahnutý v Direct3D lighting and transformation engine. Pri použití tohto typu je na každý vertex najprv aplikované svetlo a potom hmla. Je dosť podivuhodné, že hmla sa dá zapnúť aj keď je svetelný engine D3D vypnutý (D3DRS_LIGHTING je False).
Parametre hmly
Oba typy majú rovnaké parametre, ktoré treba zadať renderovaciemu zariadeniu. Jedinou výnimkou je Range-Based Fog, ktorý môžete povoliť iba pre vertex fog.
Farba (D3DRS_FOGCOLOR) - farba hmly, ktorá je miešaná s pôvodnou farbou objektu (v RGB)
Vzorec (CONST_D3DFOGMODE) - vzorec, podľa ktorého sa vypočíta fog factor - určuje pomer pôvodnej a fog farby.
D3DFOG_LINEAR

Grafom tohto vzorca je lineárna funkcia (pozri graf nižšie). Start označuje začiatok hmly a End koniec. Objekty pred začiatkom hmly nie sú ňou ovplyvnené. Za Endom sa hmla už nezosilňuje. D je vzdialenosť objektu od kamery alebo jeho hĺbka v scéne. Výsledkom je f - fog factor. Čím je väčší, tým viac pôvodnej farby sa zachovalo.
D3DFOG_EXP

D3DFOG_EXP2

D3DFOG_EXP a D3DFOG_EXP2 sú exponenciálne funkcie. Tu je fog factor závislý na hustote hmly a vzdialenosti d. Eulerovo číslo e je konštanta a má hodnotu približne 2.71828
V DX8 SDK som našiel jeden pekný graf. Všimnite si ako sa mení fog factor vzávislosti na vzdialenosti objektu.

Od toho, aký typ vzorca použijete, sa odvíjajú ďalšie parametre. Stačí sa pozrieť na vzorec a je jasné, že pre D3DFOG_LINEAR treba zadať:
FogStart (D3DRS_FOGSTART) - začiatok hmly
FogEnd (D3DRS_FOGEND) - koniec hmly
Kdežto s D3DFOG_EXP a D3DFOG_EXP2 sa spája iba jediný:
Density (D3DRS_DENSITY) - hustota hmly. Je v rozsahu <0,1>. Defaultná hodnota je 1.
Range-Based Fog (D3DRS_RANGEFOGENABLE) - môže sa použiť iba s vertex fog. Tu treba vysvetliť rozdiel medzi pojmami hĺbka objektu a vzdialenosť od kamery (vo vzorci majú oba značku d). Pozrite sa na obrázok. Sivý obdĺžnik predstavuje oblasť hmly, červený bod predstavuje kameru. Či sa objekt nachádza v hmle závisí na jeho hĺbke v scéne. V prvom prípade je iba objekt 1 v hmle. Keď sa kamera otočí, prepočíta sa znova hĺbka objektov. Vidíme, že teraz je už aj objekt 2 v hmle. Jeho hĺbka sa rotáciou kamery zmenila. Vzniká tak niekedy nechcený efekt: Objekt sa postupne stráca/objavuje pri rotácii kamery. Na rovnakom princípe pracuje aj Z-buffer (preto sa používa názov aj depth buffer). Z toho vyplýva, že všetky body, ktoré ležia na priamke (s normálovým vektorom smerujúcim ku kamere) majú v danom okamihu rovnakú hĺbku.

V prípade, že zapnete Range-Based Fog, nebude D3D počítať fog factor na základe hĺbky objektu v scéne (ako to bolo, keď bola táto funkcia vypnutá), ale na zákl. jeho vzdialenosti od kamery. Keď sa pozriete na druhý obrázok, vidíte, že fog factor sa pri rotácii nemení. Preto všetky body, ktoré ležia na kružnici majú rovnakú vzdialenosť od kamery.

Skúste v projekte vypnúť a potom zapnúť Range-Based Fog a hneď spozorujete rozdiel.
Použitie
Vytvoriť hmlu je veľmi jednoduché. V podstate stačí iba všetky potrebné parametre, už nami známou funkciou SetRenderState, odoslať renderovaciemu zariadeniu. Napísal som si jednoduchú funkciu, ktorá sa o to postará.
Sub SetupFog(FogType As CONST_D3DRENDERSTATETYPE, Color As Long,_ FogMode As CONST_D3DFOGMODE, Optional FogStart As Single,_ Optional FogEnd As Single,Optional UseRange As Boolean, _ Optional Density As Single) 'Zapneme hmlu Call D3DDevice.SetRenderState(D3DRS_FOGENABLE, True) 'Farba hmly Call D3DDevice.SetRenderState(D3DRS_FOGCOLOR, Color) If FogMode = D3DFOG_LINEAR Then 'Linear fog Call D3DDevice.SetRenderState(FogType, FogMode) Call D3DDevice.SetRenderState(D3DRS_FOGSTART, FtoDW(FogStart)) Call D3DDevice.SetRenderState(D3DRS_FOGEND, FtoDW(FogEnd)) Else 'Exponencial fog Call D3DDevice.SetRenderState(FogType, FogMode) Call D3DDevice.SetRenderState(D3DRS_FOGDENSITY, FtoDW(Density)) End If If UseRange = True Then Call D3DDevice.SetRenderState(D3DRS_RANGEFOGENABLE, True) End Sub
Najskôr treba zapnúť hmlu a nastaviť farbu. Hmla postihuje iba objekty a nie pozadie scény. Preto je lepšie nastaviť farbu pozadia (pri čistení obrazovky) rovnakú ako je farba hmly. Ďalej sa funkcia vetví podľa toho, či je zadaná lineárna alebo exponenciálna hmla. Nakoniec zapína Range-Based Fog. Všimnite si, že sme museli opäť použiť funkciu FtoDW, ktorá konvertuje Single na Long (pozri lekciu 9). Potom volanie funkcie SetupFog môže vyzerať napr. takto:
Call SetupFog(D3DRS_FOGVERTEXMODE, RGB(100, 195, 255), D3DFOG_LINEAR, 28, 50, True)
alebo
Call SetupFog(D3DRS_FOGTABLEMODE, RGB(100, 195, 255), D3DFOG_EXP2, , , , 0.05)
Na záver: V zdrojovom kóde je upravený formulár z 3D room. Je v ňom pridaná funkcia FtoDW a SetupFog a jej volanie v procedúre Form_Load. Stačí iba nahradiť starý súbor týmto.