Hlavní navigace

Procedurální textury v POV-Rayi

10. 6. 2008
Doba čtení: 11 minut

Sdílet

V dnešní části našeho seriálu o programu POV-Ray budou ukázány dva příklady využití Phongova osvětlovacího modelu. Také si popíšeme způsoby texturování těles, zejména však procedurální textury, protože právě ty tvoří základ pro tvorbu realistických povrchů, například dřeva, mramoru, textilií apod.

Obsah

1. Dokončení předchozí části: Phongův osvětlovací model prakticky
2. První demonstrační příklad: změna ambientní a difúzní složky Phongova osvětlovacího modelu
3. Druhý demonstrační příklad: změna koeficientu odlesků Phongova osvětlovacího modelu
4. Nanášení textur na povrch těles
5. Procedurální textury v POV-Rayi
6. Obsah další části seriálu

1. Dokončení předchozí části: Phongův osvětlovací model prakticky

V předchozí části tohoto seriálu jsme si popsali Phongův osvětlovací model. Stručně řečeno lze říci, že intenzita světla odraženého od povrchu předmětu je vypočtena na základě tří složek. První složkou je všesměrové (ambientní) světlo, které přichází ze všech stran a odráží se také do všech stran. Druhou složkou je difúzní světlo, jehož intenzita závisí na vzájemné poloze povrchu tělesa a světelného zdroje – čím kolměji světelný zdroj osvětluje plochu, tím je intenzita difúzní části světla větší. Poslední složkou je odražené (specular) světlo, jehož intenzita závisí na odchylce odraženého paprsku od vektoru směřujícího k pozorovateli – intenzita tohoto světla je nejvyšší v případě, že se paprsek jdoucí ze světelného zdroje odrazí přímo k pozorovateli (tento fenomén samozřejmě známe i z reálného světa, viz „prasátka“ odražená například od vzdáleného zavírajícího se okna). V POV-Rayi je možné všechny tři složky (resp. jejich koeficienty) zapsat pomocí uzlu finish:

// uzel, pomocí něhož se specifikují parametry Phongova osvětlovacího modelu
finish {
    ambient    barva_ambientního_světla // většinou zapsáno formou třísložkového vektoru
    diffuse    koeficient 0-1           // odpovídá 0% až 100% difúzní složky
    phong      koeficient 0-1           // odpovídá 0% až 100% odrazivé složky
    phong_size koeficient >=0           // odpovídá mocnině n
} 

2. První demonstrační příklad: změna ambientní a difúzní složky Phongova osvětlovacího mo­delu

V dnešním prvním demonstračním příkladu je ukázán způsob změny ambientní a současně i difúzní složky při specifikaci optických parametrů povrchů těles za pomoci Phongova osvětlovacího modelu. Ve scéně je vytvořeno celkem 5×5 geometricky zcela totožných těles osvětlených bílým světlem (konkrétně se jedná o bodový světelný zdroj), které jsou zobrazeny s využitím ortogonálního mapování (bez zkreslení vlivem perspektivy). Ve vodorovném směru se na povrchu těchto těles mění difúzní složka, ve směru svislém pak složka ambientní. Ambientní složka se mění od hodnoty <0, 0, 0>, tj. absolutně černé barvy až po hodnotu <1, 1, 1>, tj. bílou barvu. Difúzní složka nabývá hodnot od 0,0 (0%) do 1,0 (100%). Globální hodnota ambientního (všesměrového) osvětlení je nastavena na šedou barvu, protože se tato hodnota vždy násobí ambientní složkou platnou pro daný povrch. Zdrojový kód prvního demonstračního příkladu vypadá následovně:

// ------------------------------------------------------------
// První demonstrační příklad na využití Phongova osvětlovacího
// modelu.
//
// Změna ambientní a difúzní složky.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iphong.pov +Ophong.png
// (pro náhled postačí zadat povray phong.pov)
// ------------------------------------------------------------

global_settings {
    assumed_gamma 2.2
    ambient_light <0.5, 0.5, 0.5>        // ambientní složka materiálu se násobí touto konstantou
}

camera {
   orthographic                          // vypnutí perspektivního zkreslení
   location <0, 0, -10>                  // umístění kamery
   right    4/3 * x * 20                 // vektor směřující doprava
   up       y * 20                       // a nahoru
   look_at  <0, 0, 0>                    // bod, na který se kamera zaměřila
}

light_source {                           // první světelný zdroj
    <50, 50, -100>                       // pozice světelného zdroje
    color red 1.0 green 1.0 blue 1.0     // barva světelného zdroje
}

light_source {                           // druhý světelný zdroj
    <0, 0, -10000>                       // pozice světelného zdroje
    color red 0.2 green 0.2 blue 0.2     // barva světelného zdroje
    shadowless
}

plane {                                  // rovina tvořící pozadí scény
    <0, 0, 1>, 3                         // posun a orientace roviny
    hollow on
    pigment {                            // procedurální textura
        agate
        agate_turb 0.3
    }
    finish {                             // optické vlastnosti materiálu povrchu
        ambient 0.1
        diffuse 0.4
    }
}

// pozice jednotlivých objektů ve scéně
#declare Row1 =  +8;
#declare Row2 =  +4;
#declare Row3 =   0;
#declare Row4 =  -4;
#declare Row5 =  -8;
#declare Col1 = -10;
#declare Col2 =  -5;
#declare Col3 =   0;
#declare Col4 =  +5;
#declare Col5 = +10;

// textura
#declare Tex =
texture {
    pigment {
        color red 1 green 0 blue 0
    }
}

// následují jednotlivé objekty

sphere { <Col1, Row1, 0> 1.5 texture { Tex } finish {ambient <0.00, 0.00, 0.00> diffuse 0.00} }
sphere { <Col2, Row1, 0> 1.5 texture { Tex } finish {ambient <0.00, 0.00, 0.00> diffuse 0.25} }
sphere { <Col3, Row1, 0> 1.5 texture { Tex } finish {ambient <0.00, 0.00, 0.00> diffuse 0.50} }
sphere { <Col4, Row1, 0> 1.5 texture { Tex } finish {ambient <0.00, 0.00, 0.00> diffuse 0.75} }
sphere { <Col5, Row1, 0> 1.5 texture { Tex } finish {ambient <0.00, 0.00, 0.00> diffuse 1.00} }

sphere { <Col1, Row2, 0> 1.5 texture { Tex } finish {ambient <0.25, 0.25, 0.25> diffuse 0.00} }
sphere { <Col2, Row2, 0> 1.5 texture { Tex } finish {ambient <0.25, 0.25, 0.25> diffuse 0.25} }
sphere { <Col3, Row2, 0> 1.5 texture { Tex } finish {ambient <0.25, 0.25, 0.25> diffuse 0.50} }
sphere { <Col4, Row2, 0> 1.5 texture { Tex } finish {ambient <0.25, 0.25, 0.25> diffuse 0.75} }
sphere { <Col5, Row2, 0> 1.5 texture { Tex } finish {ambient <0.25, 0.25, 0.25> diffuse 1.00} }

sphere { <Col1, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.00} }
sphere { <Col2, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.25} }
sphere { <Col3, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50} }
sphere { <Col4, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.75} }
sphere { <Col5, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 1.00} }

sphere { <Col1, Row4, 0> 1.5 texture { Tex } finish {ambient <0.75, 0.75, 0.75> diffuse 0.00} }
sphere { <Col2, Row4, 0> 1.5 texture { Tex } finish {ambient <0.75, 0.75, 0.75> diffuse 0.25} }
sphere { <Col3, Row4, 0> 1.5 texture { Tex } finish {ambient <0.75, 0.75, 0.75> diffuse 0.50} }
sphere { <Col4, Row4, 0> 1.5 texture { Tex } finish {ambient <0.75, 0.75, 0.75> diffuse 0.75} }
sphere { <Col5, Row4, 0> 1.5 texture { Tex } finish {ambient <0.75, 0.75, 0.75> diffuse 1.00} }

sphere { <Col1, Row5, 0> 1.5 texture { Tex } finish {ambient <1.00, 1.00, 1.00> diffuse 0.00} }
sphere { <Col2, Row5, 0> 1.5 texture { Tex } finish {ambient <1.00, 1.00, 1.00> diffuse 0.25} }
sphere { <Col3, Row5, 0> 1.5 texture { Tex } finish {ambient <1.00, 1.00, 1.00> diffuse 0.50} }
sphere { <Col4, Row5, 0> 1.5 texture { Tex } finish {ambient <1.00, 1.00, 1.00> diffuse 0.75} }
sphere { <Col5, Row5, 0> 1.5 texture { Tex } finish {ambient <1.00, 1.00, 1.00> diffuse 1.00} }

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1501

První demonstrační příklad po vykreslení v POV-Rayi

3. Druhý demonstrační příklad: změna koeficientu odlesků Phongova osvětlovacího mo­delu

Ve druhém demonstračním příkladu zůstává ambientní i difúzní složka světla pro všechny objekty konstantní, mění se však intenzita odlesků (ve vodorovném směru). Ve směru svislém se postupně zvyšuje mocnina n, která určuje jak velikost „prasátka“, tak i rychlost změny intenzity světla od jeho středu směrem k okraji. Čím je hodnota n vyšší, tím menší, ale zato kontrastnější „prasátko“ se vytvoří. Zdrojový kód tohoto příkladu má tvar:

// ------------------------------------------------------------
// Druhý demonstrační příklad na využití Phongova osvětlovacího
// modelu.
//
// Změna odlesků.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iphong.pov +Ophong.png
// (pro náhled postačí zadat povray phong.pov)
// ------------------------------------------------------------

global_settings {
    assumed_gamma 2.2
    ambient_light <0.5, 0.5, 0.5>        // ambientní složka materiálu se násobí touto konstantou
}

camera {
   orthographic                          // vypnutí perspektivního zkreslení
   location <0, 0, -10>                  // umístění kamery
   right    4/3 * x * 20                 // vektor směřující doprava
   up       y * 20                       // a nahoru
   look_at  <0, 0, 0>                    // bod, na který se kamera zaměřila
}

light_source {                           // první světelný zdroj
    <50, 50, -100>                       // pozice světelného zdroje
    color red 1.0 green 1.0 blue 1.0     // barva světelného zdroje
}

light_source {                           // druhý světelný zdroj
    <0, 0, -10000>                       // pozice světelného zdroje
    color red 0.2 green 0.2 blue 0.2     // barva světelného zdroje
    shadowless
}

plane {                                  // rovina tvořící pozadí scény
    <0, 0, 1>, 3                         // posun a orientace roviny
    hollow on
    pigment {                            // procedurální textura
        agate
        agate_turb 0.3
    }
    finish {                             // optické vlastnosti materiálu povrchu
        ambient 0.1
        diffuse 0.4
    }
}

// pozice jednotlivých objektů ve scéně
#declare Row1 =  +8;
#declare Row2 =  +4;
#declare Row3 =   0;
#declare Row4 =  -4;
#declare Row5 =  -8;
#declare Col1 = -10;
#declare Col2 =  -5;
#declare Col3 =   0;
#declare Col4 =  +5;
#declare Col5 = +10;

// textura
#declare Tex =
texture {
    pigment {
        color red 1 green 0 blue 0
    }
}

// následují jednotlivé objekty

sphere { <Col1, Row1, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.00 phong_size 1} }
sphere { <Col2, Row1, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.25 phong_size 1} }
sphere { <Col3, Row1, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.50 phong_size 1} }
sphere { <Col4, Row1, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.75 phong_size 1} }
sphere { <Col5, Row1, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 1.00 phong_size 1} }

sphere { <Col1, Row2, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.00 phong_size 5} }
sphere { <Col2, Row2, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.25 phong_size 5} }
sphere { <Col3, Row2, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.50 phong_size 5} }
sphere { <Col4, Row2, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.75 phong_size 5} }
sphere { <Col5, Row2, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 1.00 phong_size 5} }

sphere { <Col1, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.00 phong_size 10} }
sphere { <Col2, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.25 phong_size 10} }
sphere { <Col3, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.50 phong_size 10} }
sphere { <Col4, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.75 phong_size 10} }
sphere { <Col5, Row3, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 1.00 phong_size 10} }

sphere { <Col1, Row4, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.00 phong_size 20} }
sphere { <Col2, Row4, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.25 phong_size 20} }
sphere { <Col3, Row4, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.50 phong_size 20} }
sphere { <Col4, Row4, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.75 phong_size 20} }
sphere { <Col5, Row4, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 1.00 phong_size 20} }

sphere { <Col1, Row5, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.00 phong_size 50} }
sphere { <Col2, Row5, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.25 phong_size 50} }
sphere { <Col3, Row5, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.50 phong_size 50} }
sphere { <Col4, Row5, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 0.75 phong_size 50} }
sphere { <Col5, Row5, 0> 1.5 texture { Tex } finish {ambient <0.50, 0.50, 0.50> diffuse 0.50 phong 1.00 phong_size 50} }

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1502

Druhý demonstrační příklad po vykreslení v POV-Rayi

4. Nanášení textur na povrch těles

V POV-Rayi je možné popsat vizuální vlastnosti povrchu modelovaných těles několika různými způsoby, popř. i jejich kombinacemi. Nejjednodušší je specifikace konstantní barvy materiálu, ze kterého je těleso složeno. Tímto způsobem, se kterým jsme se už setkali prakticky ve všech demonstračních příkladech, však lze vytvářet pouze ty nejjednodušší scény. Jednobarevná tělesa se často používají u technických modelů (strojnictví, stavitelství, technický design), u kterých je větší důraz kladen na geometrii těles (jejich tvar) a ne na fotorealističnost výsledné scény. To je ostatně patrné i z prvního obrázku, jehož předlohu jsme si ukázali v předchozích částech tohoto seriálu.

povray1503

Scéna, u níž je dbáno především na tvar jednotlivých součástek a ne na fotorealističnost výsledku

Další možností je nanesení dvojrozměrné textury na povrch tělesa. Dvojrozměrná textura může být uložena v externím souboru jako běžný rastrový obrázek, což je pro mnoho aplikací výhodné – je například možné do pozadí vykreslované scény vložit fotografii nebo některé tvarově složité objekty nahradit pouhým obdélníkem s nanesenou texturou (s některými průhlednými pixely) – tato technika, který bývá v různých obměnách použita i u počítačových her, se nazývá billboarding.

povray1505

Rastrová textura tvořící plochu okna obsahuje průhledné pixely

Ovšem tento typ textur přináší při svém použití i některé nevýhody: velké nároky na kapacitu operační paměti, především při použití velkých rastrových obrázků, vznik aliasu, který v tomto případě není možné zcela potlačit (zejména u animací, tj. tvorbě snímků, které se od sebe liší pouze v malých detailech) a v neposlední řadě také to, že 2D obrázek, tj. původně obdélník, je při nanesení na obecný povrch tělesa nutně zborcený. V každém případě se těmto typům textur budeme do všech podrobností věnovat v navazujících částech tohoto seriálu.

povray1506

Scéna, ve které jsou použity textury uložené v rastrových obrázcích

5. Procedurální textury v POV-Rayi

V POV-Rai existuje ještě jeden způsob, jakým je možné povrch těles pokrýt texturou. Jedná se o velmi dobře propracovanou technologii takzvaných procedurálních textur. Tyto textury nejsou reprezentovány rastrovým obrázkem, ale matematickým výrazem, který každému bodu ležícímu v trojrozměrném prostoru přiřazuje jeho barvu, tj. jedná se o funkci color=f(x,y,z). Vzhledem k tomu, že má funkce definiční obor R3, nedochází většinou (výjimky se najdou) při použití procedurálních textur k nežádoucímu aliasu a nároky na kapacitu operační paměti jsou také mnohem menší, protože procedurální textura se vlastně nevytváří dopředu (není uložena ani v operační paměti, ani v externím souboru), jelikož se barva jednotlivých bodů na povrchu těles počítá až při vlastním renderingu. Tato vlastnost je s oblibou použita například při vykreslování na renderovacích farmách složených z počítačů bez pevného disku (ušetří se jak přenosová kapacita propojovací sítě, tak i operační paměť jednotlivých výpočetních uzlů v renderovací farmě).

povray1507

Příklad použití procedurálních textur

Díky tomu, že procedurální textury vyplňují celý trojrozměrný prostor, ze kterého vykreslované těleso v podstatě „vyřezává“ obsazený podprostor, nedochází k žádnému zborcení procedurální textury na povrchu tělesa, i když v mnoha případech je obrazec textury závislý na směru řezu. Jak již bylo napsáno v předchozím odstavci, je procedurální textura specifikována nějakou funkcí. V POV-Rayi lze vhodnou funkci zapsat buď přímo ve formě matematického výrazu nebo se – a to v praxi mnohem častěji – použijí již předdefinované procedurální textury, u nichž lze změnit jejich parametry a barvy (popř. barvové přechody), které jsou v textuře použity. Takový způsob zápisu textury je nejenom velmi úsporný, ale i přenositelný na různé platformy. V minulosti sice existovaly nepatrné rozdíly ve způsobu výpočtu některých procedurálních textur (například u textur používajících generátor náhodných čísel), dnes je však zaručeno – a to i zpětně – že bude procedurální textura vykreslena vždy stejným způsobem.

povray1508

Procedurální textury dřeva

UX DAy - tip 2

6. Obsah další části seriálu

V následující části tohoto seriálu si popíšeme další typy procedurálních textur, které je možné v POV-Rayi použít, i způsoby jejich modifikace pomocí různých parametrů. Vzhledem k tomu, že textury nemusí být použity pouze pro vytvoření barevného obrazce na povrchu těles, ale mohou sloužit i pro další činnosti, například modulaci normálových vektorů na stěnách těles (bump mapping), budou příště popsány i tyto zajímavé a v oblasti 3D graficky často používané techniky.

povray1509

Ukázka bump mappingu (modifikace normálových vektorů na kouli)

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.