|
                         |
                         |              +--+--+
                         +-----+ |    | |  |  | +----+
                         |     | |    | |  |  | |    |                          
                         |     | |    | |     | |    |
                         +-----+ +----+ |     | +----+
                                                |
                                     mapping 

              V  minulém  čísle  jsem  vám  nastínil  možnosti geniálního
        environment  mappingu,  jehož  výhodně využijeme při implementaci
        časově náročnějšího  bump mappingu, který dává opravdu vynikající
        výsledky  co  do  vizuální  věrnosti výsledného  produktu. Předem
        upozorňuji  ty  z  vás,  kteří  do  texturovacích  technik příliš
        nevidíte,  že  po  přečtení  tohoto  článku by se vám možná mohla
        stát  jedna  nepříjemná  věc.  Je to podobné jako u texturovacích
        metod.  Když  nezasvěcený  pozorovatel  zhlédne scénu s lineárním
        texturemappingem  a potom s perspektivní korekcí, netuší v čem je
        rozdíl  a  zkonstatuje,  že  ten  první  průlet  byl  asi dvakrát
        plynulejší.  Ale jakmile mu celou problematiky vysvětlíte a on se
        začne  pozorněji  dívat,  po  nějakém  čase  zaregistruje spoustu
        optických chyb, které mu před tím unikaly. Neuplyne dlouhá doba a
        bývalý  laik  bezpečně  pozná  rozdíl  mez lineární interpolací a
        perspektivní  korekcí.  Zvláště  pro  programátory,  kteří vyvíjí
        nějaké  engine  je  tento  fakt velmi destruktivní, jelikož věci,
        které se jim kdysi líbily najednou ztrácejí svojí optickou krásu.
        Tato  profesionální  deformace  se projevuje také u environment a
        bump  mappingu. Takže pokud máte rádi některé scény a nechcete si
        nechat  zkazit  dobrý dojem, dívejte se raději stále svým laickým
        okem  a  nepokoušejte  se  proniknout  do tajů těchto metod. Bump
        mapping  je  pro  laiky opravdu značně realistický, zvláště pokud
        je  objekt  ve vzdálenosti "zlatého řezu", tedy tam, kde se poměr
        mezi rastrem obrazovky a textury blíží jedné. K jeho implementaci
        potřebujeme   celkem  tři  textury.  Jedna  reprezentuje  vlastní
        materiál objektu, druhá jeho nerovnosti a třetí phong environment
        mapu. Poslední dvě si popíšeme podrobněji.

              Bump mapa je textura, která by měla mít stejné rozměry jako
        textura materiálová. Její paleta není samozřejmě důležitá, závisí
        pouze na indexech jednotlivých barev. Nejlépe je si zvolit jako 0
        největší  prohlubeň  a 127 jako největší výstupek. Proč právě 127
        si objasníme později. Phong mapa je jednoduchá environment mapa s
        předpočítaným  hotspotem  světla, tak, jak jsem ji popisoval a na
        obrázku  ukazoval  v  minulém čísle. Zde zase nezáleží na paletě,
        ale  pouze  na  indexech barev, takže je logické si zvolit 0 jako
        minimální  a  63  maximální intenzitu. Rozsah 0 až 255 je v praxi
        zbytečně veliký, protože lidské oko je schopné rozlišit přibližně
        64 odstínů jedné barvy.

              Další  tabulku  hodnot,  kterou  budeme  potřebovat,  pokud
        pracujeme  v 256 barevných režimech, je jednoduchá lookup tabulka
        pro  převod  intenzity  na  konečnou  barvu.  Na  její  vytvoření
        existuje  spousta  metod,  asi  nejjednodušší je hledání nebližší
        barvy  dané  intenzity pomocí vzdálenosti v RGB krychli. Případné
        zájemce  odkazuji  na  Liborův  článek v tomto čísle. Rozsah této
        tabulky  závisí  na  zvoleném  indexování  Phong mapy. Je výhodné
        zvolit  64  odstínů,  takže  výsledná  velikost bude 256*64=16384
        bajtů.

              Poslední  paměť  musíme  alokovat pro velice důležitou bump
        tabulku,  která  sice  není úplně nezbytná, ale výrazně urychluje
        vykreslování bump mapovaného polygonu. Bude mít stejný počet bodů
        jako   bump   mapa,  kterou  budeme  moci  po  provedení  jistých
        inicializačních  kalkulací uvolnit z paměti. Jediný rozdíl bude v
        tom,  že  bude  moci obsahovat i záporná čísla v rozsahu paměťové
        velikosti  textury  tedy  například  od -32767 do +32767. Abychom
        pochopili   její  význam,  musíme  si  nejdřív  objasnit  vlastní
        podstatu bump mappingu.

              Samotná  teorie prostorových textur je poměrně komplikovaná
        a  její  podstata  tkví na stejném základě jako například Phongův
        osvětlovací  model.  Abychom  docílili  opravdové přesnosti, měli
        bychom   počítat  úhel,  který  svírá  normála  nerovné  plochy s
        vektorem  světla.  Implementace nerovnosti povrchu zvýšením počtu
        polygonů je zajisté možná, ale jak už asi všichni tušíte, není ta
        nejlepší.  Její  realističnost  je sice zachována i při relativně
        velkém  přiblížení  k  objektu,  ale optimalizace s cílem redukce
        časově  náročných  operací  v  plovoucí  čárce  je  i pro výkonné
        procesory  stále  aktuální.  Ve  světě počítačů s procesory firmy
        Intel  se  jakékoli  zvýšení  počtu polygonů nad nutnou mez stává
        fatálním.  Veškeré  low-level  optimalizace vykreslování polygonů
        jdou  automaticky  stranou,  pokud  je  scéna  složena  z velkého
        množství  relativně  malých  polygonů.  Tento problém lze poměrně
        elegantně  vyřešit  následujícím  způsobem.  Spočteme  gradient v
        každém  bodě  textury,  která  reprezentuje nerovnost materiálu a
        pomocí  velice  rychlé  rutiny,  která se nijak výrazně neliší od
        phong  texture  mappingu  pokryjeme nesrovnatelně větší polygony.
        Tato  simulace  má  ovšem  jedno  úskalí.  Pokud  se přiblížíme k
        objektu na vzdálenost, kdy se rastr textury značně liší od rastru
        obrazovky,  výsledný  efekt  nenávratně  vymizí  a  objekt ztratí
        původní plastičnost. Tato skutečnost se v mnohých profesionálních
        systémech  řeší dynamickou náhradou polygonového detailu povrchu.
        Výpočet   gradientu   je   velice  jednoduchá  záležitost,  pokud
        využijeme   zjednodušené   implementace   bump   mappingu  pomocí
        prostorových textur s pevnou velikostí.

                                  ....+---+....
                                  :   | c |   :
                                  +---+-+-+---+
                                  | a |x|y| b |
                                  +---+-+-+---+
                                  :   | d |   :
                                  ....+---+....

               grad[x] = b-a = bump_mapa[x-1][y]-bump_mapa[x+1][y]
               grad[y] = d-c = bump_mapa[x][y-1]-bump_mapa[x][y+1]

        Ve  své podstatě nám obě hodnotu udávají sklon elementární plošky
        ve  směru  dané osy. Pro jednoduchost zvolíme vektor světla kolmý
        na  počítaný  povrch a z  této  podmínky  je  už  snadné  odvodit
        intenzitu odráženého světla na elementární plošce:

                     intenzita[x][y] = max-(grad[x]+grad[y])

        Jak  je  vidět,  maximální  intenzitu bude mít odražené světlo na
        plošce,  jejíž gradient bude nulový ve směru osy X respektive osy
        Y.  Tento fakt využijeme při samotném vykreslování polygonu. Nyní
        se  vraťme  k bump tabulce. Právě do ní budeme ukládat jednotlivé
        gradienty, kterými v konečné  fázi vychýlíme  UV vektor ukazující
        do envirnoment textury. Doufám, že je zřejmé, že tím snížíme nebo
        naopak  zvýšíme  intenzitu  ve vykreslovaném bodě. Pochopit tento
        fakt   je  poněkud  složitější,  takže  jsem  pro  vás  připravil
        ilustrační obrázek .Pokud si představíte, že levé bílé políčko má
        hloubku 0 a pravé 127, potom je  obrázek reálný.  Je z něj vidět,
        že  čím větší je rozdíl mezi hloubkami okolních bodů, tím více se
        odchýlí  UV  vektor  a  ukazuje  na  tím menší intenzitu. Proč je
        maximální hloubka 127, je už snad jasné. Bump textura o velikosti
        256x256  má  střed  právě v bodě [127,127]. Hodnoty, které budeme
        ukládat do bump tabulky získáme zřejmě následovně:

            bump_tab[x][y] = bump_mapa[x-1][y]-bump_mapa[x+1][y]+
                            (bump_mapa[x][y-1]-bump_mapa[x][y+1])*256

        Proč  je tam  to násobení 256 ? Je to jednoduché. Jak jistě víte,
        intenzita bodu se pomocí phong textury spočítá následovně:

                      intenzita[u][v] = phong_mapa[u+v*256],

        takže když bychom to rozepsali pro bump mapping pomocí gradientů:

         intenzita[tU][tV] = phong_mapa[(pU-grad[tU])+(pV-grad[tV])*256],

        kde  pU  a  pV  jsou  souřadnice  bodu v phong textuře a tU, tV v
        materiálové  textuře.  Když  to upravíme pomocí předpočítané bump
        tabulky, získáme výsledný vztah pro intenzitu v daném bodě:

            intenzita[tU][tV] = phong_mapa[pU+pV*256-bump_tab[tU][tV]]

              Pokud  to stále nechápete, zkuste si to sami odvodit. Je to
        myslím  poměrně  jednoduché  a  pochopitelné.  V praxi by se daly
        použít    následující   rutiny   (předpočítání   bump   tabulky a
        vykreslovací  smyčka)  napsané  v  C,  které  GNU  C  kompilátory
        spolehlivě zoptimalizují:

          for (i=1;i<255;i++)
              for (j=1;j<255;j++) {
                  ofs=i+j*256;
                  bump_tab[ofs]=bump_mapa[ofs-1]-bump_mapa[ofs+1]+
                  ((bump_mapa[ofs-256]-bump_mapa[ofs+256])<<8);
                  }

          while (output<=end) {
                int tUV=tU+(tV<<8);
                int pUV=pU+(pV<<8)-bump_tab[tUV];
                *output++=shadow_tab[(textura[tUV]<<6)+phong_mapa[pUV]];
                tU+=dtU;
                tV+=dtV;
                pU+=dpU;
                pV+=dpV;
                }

              Na  závěr podotýkám, že nejvíce bump mapping vynikne, pokud
        je  objekt  v  pohybu,  protože  právě  malá změna pozice objektu
        vyvolá  mnohdy relativně velkou změny intenzity různě vystouplých
        bodů, podobně  jako  je  tomu  v  reálném světě, kterému se stále
        snažíme  přiblížit. Někdy  se ptám, proč tak vlastně činíme, když
        stačí  vypnout  počítač  a  vyrazit  do  přírody,  kde to všechno
        funguje nekonečně plynule a přesně. :-]

                                                           ReDox


            výheň