Hlavní navigace

Izoplochy v POV-Rayi aneb vizuální matematika

13. 5. 2008
Doba čtení: 13 minut

Sdílet

V dnešní části seriálu o renderovacím programu POV-Ray si popíšeme jeden z nejzajímavějších typů objektů, které je možné v této aplikaci při tvorbě 3D scén použít. Jedná se o takzvané izoplochy, pomocí nichž je možno velmi snadno vymodelovat celou řadu různých tvarů těles a dalších objektů.

Obsah

1. Teorie izoploch
2. Izoplochy v POV-Rayi
3. První demonstrační příklad – jednoduchá tělesa vytvořená pomocí izoploch
4. Druhý demonstrační příklad – průběhy 2D funkcí
5. Třetí demonstrační příklad – implementace jednoduchého CSG
6. Čtvrtý demonstrační příklad – slévání objektů
7. Použití šumových funkcí
8. Pátý demonstrační příklad – použití šumových funkcí

1. Teorie izoploch

Izoplochy implementované v POV-Rayi se dosti zásadním způsobem odlišují od všech předchozích typů těles, které jsme si prozatím popisovali. Rozdíl spočívá v tom, že izoplochy jsou zadané nějakou implicitní funkcí, přičemž je tato funkce zapsána přímo do zdrojového kódu programu. To je sice na první pohled mnohem složitější než použití již hotových a předdefinovaných těles, ovšem na druhou stranu se mohou izoplochy použít pro mnoho účelů, například při vlastní implementaci CSG (s možností libovolně definovaného prolínání těles), tvorbě objektů vytvořených z porézních materiálů (použití šumových funkcí), vytváření povrchů modulovaných nějakou další funkcí (hrbolky, vlnky) atd. V podstatě se dá říci, že jediným typem tělesa, které by mohl nějaký minimalistický raytracer umět vykreslit, je explicitně zadaná izoplocha. Ve skutečnosti by však práce s takovým programem byla velmi pomalá, protože pro vykreslení obecných ploch je zapotřebí implementovat i složitější algoritmy, než pro jednodušší tělesa složená z plošek či kvadrik.

povray1101

Scéna, jejíž podstatná část je vymodelována pomocí izoploch

Jak již bylo napsáno v předchozím odstavci, je izoplocha definována nějakou implicitní funkcí, například abs(x)+abs(y)+ab­s(z)-2, která pro každý bod v prostoru určuje jeho „potenciál“, což je libovolné reálné číslo. Dále je zapotřebí specifikovat takzvanou prahovou hodnotu (threshold), pomocí nějž se ze všech bodů vyberou ty, které na izoploše leží – v podstatě se prahovou hodnotou vybírá některá ekvipotenciální plocha. Změnou prahové hodnoty se do značné míry dá ovlivňovat tvar výsledné izoplochy. Vzhledem k tomu, že izoplochy mohou být nekonečné (záleží na jejich konkrétním tvaru), přidává se v POV-Rayi k izoploše ještě obalové těleso, které má typicky tvar kvádru či koule. Pomocí tohoto obalového tělesa je izoplocha omezena v prostoru, což mj. vede i k urychlení všech výpočtů průsečíků paprsků s izoplochou.

2. Izoplochy v POV-Rayi

V POV-Rayi jsou izoplochy zapsané pomocí uzlu typu isosurface. Parametry specifikované v tomto uzlu jsou následující:

isosurface {                             // uzel použitý pro zápis izoplochy
    function {
        abs(x)+abs(y)+sin(z)-2           // zápis implicitní funkce
    }
    threshold 0.0                        // prahová hodnota
    accuracy 1e-6                        // přesnost výpočtu (čím menší číslo, tím přesnější)
    max_gradient 2                       // maximální gradient
    contained_by {                       // těleso, které tvoří hranici obecně nekonečné izoplochy
        sphere {                         // v tomto případě se jedná o kouli s poloměrem 2
            <0,0,0>,2
        }
    }
    texture {                            // textura aplikovaná na izoplochu
        Solid
    }
    scale 0.9                            // lineární transformace aplikovaná na izoplochu
    rotate <-40, 30, 0>
} 

Vidíme, že v uzlu isosurface se definuje jak vlastní implicitní funkce a její prahová hodnota threshold, tak i všechny další potřebné parametry. Pomocí hodnoty accuracy se specifikuje přesnost výpočtu. Čím nižší je zde uložená hodnota, tím přesněji veškeré výpočty probíhají, ovšem samozřejmě se prodlužuje i čas vykreslení celé scény. Důležitý je také parametr max_gradient, který musí mít dostatečně velkou hodnotu, aby bylo těleso vykresleno korektně (tj. aby nechyběly některé jeho části). Ovšem příliš velká hodnota znamená také prodloužení času výpočtu. Při renderingu POV-Ray vypíše varování v případě, že je hodnota gradientu příliš vysoká či naopak nízká.

povray1102

Tělesa vymodelovaná pomocí izoploch

3. První demonstrační příklad – jednoduchá tělesa vytvořená pomocí izoploch

V prvním demonstračním příkladu je ukázána tvorba jednoduchého tělesa specifikovaného pomocí implicitní funkce a prahové hodnoty. V příkladu jsou (v poznámce) zapsány i další implicitní funkce, které je možné vyzkoušet, ovšem v tomto případě se musí změnit i měřítko tělesa pomocí lineární transformace scale). Pokud se sníží maximální hodnota gradientu, může to vést k tomu, že části tělesa budou chybět nebo těleso dokonce celé zmizí. Následuje výpis zdrojového tvaru prvního demonstračního příkladu:

// ------------------------------------------------------------
// První demonstrační příklad na použití izoploch ve scénách
// vykreslovaných pomocí POV-Raye.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Ipoly1.pov +Opoly1.png
// (pro náhled postačí zadat povray poly1.pov)
// ------------------------------------------------------------

#version 3.1;                            // specifikace verze POV-Raye

global_settings {
    assumed_gamma 2.2
}

#include "colors.inc"
#include "woods.inc"

camera {                                 // nastavení kamery,
    right x*image_width/image_height     // které odpovídá optice
    location  <0, 0, -8>                 // lidského oka
    look_at   <0, 0, 0>
    angle 35
}

// první světelný zdroj
light_source {
    <500,500,-500>
    rgb 1
}

// druhý světelný zdroj
light_source {
    <-500,500,-500>
    rgb <0.1,0.1,0.3>
    shadowless
}

// třetí světelný zdroj
light_source {
    <3,3,-3>
    rgb <1,1,1>
    shadowless
}

// povrch plochy
#declare Solid=
texture {                                // vlastnosti materiálu
    pigment {                            // procedurální textura
        agate
        agate_turb 0.7
    }
    finish {                             // odlesky
        phong 1
    }
}



isosurface {                             // specifikace izoplochy
    function {                           // implicitní funkce
        sqrt(pow(x,2) + pow(y,2) + pow(z,2)) + abs(x+z)
        //abs(x)+abs(y)+abs(z)-2
        //sqrt(pow(x,2) + pow(y,2) + pow(z,2)) - 1.0
    }
    threshold 2.0                        // prahová hodnota implicitní funkce
    accuracy 1e-6                        // přesnost výpočtu
    max_gradient 2                       // maximální hodnota gradinentu
    contained_by {                       // obalové těleso
        box {
            -2.0, 2.0
        }
    }
    texture {
        Solid
    }
    scale 0.9
    rotate <0, 30, -60>
}



// kvádr, do kterého je celá scéna uzavřena
box {
    <-10,-2,-8>, < 10, 10, 8>
    texture {
        pigment {                        // šachovnicová textura
            checker
            color <0.1, 0.3, 0.4>,
            color <0.2, 0.5, 0.7>
        }
        finish {                         // odlesky a odrazy na povrchu
            diffuse 0.7
            reflection 0.2
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1103

Obrázek vytvořený renderingem prvního demonstračního příkladu

4. Druhý demonstrační příklad – průběhy 2D funkcí

Izoplochy je možné použít také pro vykreslení průběhu 2D funkcí, tj. funkcí, které mají v originální podobě dva nezávislé parametry. To je ukázáno na dnešním druhém demonstračním příkladu, pomocí nějž se vytvoří netlumené „kruhy na vodě“, ležící v rovině x-z. Jedná se o funkci y-cos(sqrt(xx + zz)3pi)*0.1, přičemž část s parametrem y musela být přidána při převodu funkce do implicitní podoby. Při bližším prozkoumání této funkce zjistíme, že hodnota podvýrazu cos() je konstantní pro všechny body ležící ve stejné vzdálenosti od středu souřadné soustavy (sqrt představuje druhou odmocninu a počítá se pomocí ní vzdálenost bodu od počátku), což představuje základ pro vytvářené kruhy na vodě. Podobným způsobem je možné vykreslit i mnohem složitější funkce. V poznámce zdrojového kódu druhého demonstračního příkladu je zapsána funkce složená z implicitní rovnice koule doplněné o složitější variantu „kruhů na vodě“:

// ------------------------------------------------------------
// Demonstrační scéna s implicitní plochou představující průběh
// 2D funkce převedené do implicitní podoby.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Idemo2.pov +Odemo2.png
// (pro náhled postačí zadat povray demo2.pov)
// ------------------------------------------------------------

#version 3.1;                            // specifikace verze POV-Raye

global_settings {
    assumed_gamma 2.2
}

#include "colors.inc"
#include "woods.inc"

camera {                                 // nastavení kamery,
    right x*image_width/image_height     // které odpovídá optice
    location  <0, 0, -8>                 // lidského oka
    look_at   <0, 0, 0>
    angle 35
}

// první světelný zdroj
light_source {
    <500,500,-500>
    rgb 1
}

// druhý světelný zdroj
light_source {
    <-500,500,-500>
    rgb <0.1,0.1,0.3>
    shadowless
}

// třetí světelný zdroj
light_source {
    <3,3,-3>
    rgb <1,1,1>
    shadowless
}

// povrch plochy
#declare Solid=
texture {                                // vlastnosti materiálu
    pigment {                            // procedurální textura
        agate
        agate_turb 0.7
    }
    finish {                             // odlesky
        phong 1
    }
}



isosurface {
    function {
        y-cos(sqrt(x*x + z*z)*3*pi)*0.1  // 2D funkce "vlny"
            //  sqrt(x*x + y*y + z*z) - 0.9
        // +sin(12*atan2(x, z))*sin(8*atan2(y, sqrt(x*x + z*z)))*0.1

    }
    threshold 0.0                        // hranice
    accuracy 1e-6                        // přesnost výpočtu
    max_gradient 2                       // maximální gradient
    contained_by {                       // hraniční těleso
        box {
            -2.0, 2.0
        }
    }
    texture {                            // textura povrchu implicitní plochy
        Solid
    }
    scale 1.7                            // lineární transformace aplikované na plochu
    rotate <-40, 0, 0>
}



// kvádr, do kterého je celá scéna uzavřena
box {
    <-10,-2,-8>, < 10, 10, 8>
    texture {
        pigment {                        // šachovnicová textura
            checker
            color <0.1, 0.3, 0.4>,
            color <0.2, 0.5, 0.7>
        }
        finish {                         // odlesky a odrazy na povrchu
            diffuse 0.7
            reflection 0.2
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1104

Obrázek vytvořený renderingem druhého demonstračního příkladu

5. Třetí demonstrační příklad – implementace jednoduchého CSG

Volbou vhodných kombinací funkcí tvořících izoplochu je možné simulovat i takové operace, jako je konstruktivní geometrie těles (CSG – Constructive Solid Geometry), kterou jsme si již popsali v úvodních dílech tohoto seriálu. Idea simulace CSG pomocí izoploch je vlastně velmi jednoduchá, protože i CSG není vlastně nic jiného než kombinace dvou a více implicitních funkcí (i když zapisovaných nepřímo) pomocí tří základních operátorů. Vzhledem k tomu, že tyto operátory je možné zapsat formou funkce, nic nám nebrání v tom, abychom si CSG vyzkoušeli sami implementovat. Jediným rozdílem oproti „skutečnému“ CSG tak bude mnohem pomalejší běh raytraceru. Jakým způsobem je tedy možné CSG simulovat? Všechny možnosti jsou (pro dvě blíže nespecifikované implicitní funkce A a B) vypsány v následující tabulce, přičemž funkce max a min mají běžný matematický význam, není zapotřebí v nich hledat nic tajuplného:

CSG operace Význam Zápis formou izoplochy
union sjednocení min(A+B)
intersection průnik max(A+B)
difference rozdíl max(A-B)

Jakým způsobem tyto operace fungují je jednoduché pochopit poté, co si uvědomíme, že izoplocha je vlastně tvořena všemi body, které mají stejný „potenciál“ a jednotlivé funkce tvořící izoplochu vlastně určují potenciál jednotlivých geometrických bodů umístěných v prostoru. Pokud se tedy kombinují dvě funkce A a B (může jít například o implicitní funkce koule a válce), znamená aplikace min pouze to, že se na výsledné izoploše budou vyskytovat jak všechny body ležící na ploše koule, tak i všechny body ležící na válci – min zde však musí být uvedeno, protože pouhé A+B by vedlo k tomu, že by se v místě protnutí obou základních tvarů vytvořila „boule“.

Ve třetím demonstračním příkladu je ukázána aplikace CSG operace rozdílu:

// ------------------------------------------------------------
// Demonstrační scéna, ve které se pomocí izoplochy simuluje
// CSG operace rozdílu dvou těles.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Idemo3.pov +Odemo3.png
// (pro náhled postačí zadat povray demo3.pov)
// ------------------------------------------------------------

#version 3.1;                            // specifikace verze POV-Raye

global_settings {
    assumed_gamma 2.2
}

#include "colors.inc"
#include "woods.inc"

camera {                                 // nastavení kamery,
    right x*image_width/image_height     // které odpovídá optice
    location  <0, 0, -8>                 // lidského oka
    look_at   <0, 0, 0>
    angle 35
}

// první světelný zdroj
light_source {
    <500,500,-500>
    rgb 1
}

// druhý světelný zdroj
light_source {
    <-500,500,-500>
    rgb <0.1,0.1,0.3>
    shadowless
}

// třetí světelný zdroj
light_source {
    <3,3,-3>
    rgb <1,1,1>
    shadowless
}

// povrch plochy
#declare Solid=
texture {                                // vlastnosti materiálu
    pigment {                            // procedurální textura
        agate
        agate_turb 0.7
    }
    finish {                             // odlesky
        phong 1
    }
}



#declare fn_A = function { sqrt(pow(y,2) + pow(z,2)) - 0.8 } // implicitní funkce válce
#declare fn_B = function { abs(x)+abs(y)-1 }                 // implicitní funkce kvádru

isosurface {                             // izoplocha
    function {
        max(fn_A(x, y, z), -fn_B(x, y, z)) // simulace CSG operace
    }
    threshold 0.0                        // prahová hodnota
    accuracy 1e-6                        // přesnost výpočtu
    max_gradient 4                       // maximální gradient (může být i nižší)
    contained_by {                       // těleso, které tvoří hranici izoplochy
        box {
            -2.0, 2.0
        }
    }
    texture {
        Solid
    }
    rotate <0, 30, 0>                    // lineární transformace aplikovaná na izoplochu
}



// kvádr, do kterého je celá scéna uzavřena
box {
    <-10,-2,-8>, < 10, 10, 8>
    texture {
        pigment {                        // šachovnicová textura
            checker
            color <0.1, 0.3, 0.4>,
            color <0.2, 0.5, 0.7>
        }
        finish {                         // odlesky a odrazy na povrchu
            diffuse 0.7
            reflection 0.2
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1105

Obrázek vytvořený renderingem třetího demonstračního příkladu

6. Čtvrtý demonstrační příklad – slévání objektů

Ve čtvrtém demonstračním příkladu je ukázáno, jakým způsobem je možné pomocí izoploch docílit vykreslení objektu složeného ze dvou geometrických těles, které se vzájemně slévají. Funkce použitá pro slévání je svými základními vlastnostmi podobná, jako v případě už dříve popsaných blobů (metaballs) – jedná se o monotonně klesající funkci limitně se blížící k nule. V demonstračním příkladu jsou deklarovány dvě základní implicitní funkce. První funkce odpovídá válci, jehož osa prochází souřadnou osou x, druhá funkce odpovídá kvádru s osou, jež je totožná se souřadnou osou z. Kvádr je natočený o 45°. Ve zdrojovém příkladu si povšimněte toho, že není zapotřebí výslednou implicitní funkci nutně psát jedním výrazem, ale je možné použít samostatné deklarace (jedná se o řádky #declare fn_A= a #declare fn_B=. Díky tomu se zápis nejenom zjednodušil, ale také jsme obě funkce odpovídající základním tělesům mohli pojmenovat, což přispívá k čitelnosti kódu. Následuje zdrojový text čtvrtého demonstračního příkladu:

// ------------------------------------------------------------
// Demonstrační scéna s izoplochou složenou ze dvou slévajících
// se objektů.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Idemo4.pov +Odemo4.png
// (pro náhled postačí zadat povray demo4.pov)
// ------------------------------------------------------------

#version 3.1;                            // specifikace verze POV-Raye

global_settings {
    assumed_gamma 2.2
}

#include "colors.inc"
#include "woods.inc"

camera {                                 // nastavení kamery,
    right x*image_width/image_height     // které odpovídá optice
    location  <0, 0, -8>                 // lidského oka
    look_at   <0, 0, 0>
    angle 35
}

// první světelný zdroj
light_source {
    <500,500,-500>
    rgb 1
}

// druhý světelný zdroj
light_source {
    <-500,500,-500>
    rgb <0.1,0.1,0.3>
    shadowless
}

// třetí světelný zdroj
light_source {
    <3,3,-3>
    rgb <1,1,1>
    shadowless
}

// povrch plochy
#declare Solid=
texture {                                // vlastnosti materiálu
    pigment {                            // procedurální textura
        agate
        agate_turb 0.7
    }
    finish {                             // odlesky
        phong 1
    }
}

#declare fn_A = function { sqrt(pow(y,2) + pow(z,2)) - 0.8 } // implicitní funkce válce
#declare fn_B = function { abs(x)+abs(y)-1 }                 // implicitní funkce kvádru
#declare Blob_threshold=0.01;

isosurface {                             // izoplocha
    function {                           // dva objekty, které se slévají
      (1+Blob_threshold)
      -pow(Blob_threshold, fn_A(x,y,z))  // válec
      -pow(Blob_threshold, fn_B(x,y,z))  // kvádr
    }
    threshold 0.0                        // prahová hodnota
    accuracy 1e-6                        // přesnost výpočtu
    max_gradient 4                       // maximální gradient (může být i nižší)
    contained_by {                       // těleso, které tvoří hranici izoplochy
        box {
            -2.0, 2.0
        }
    }
    texture {
        Solid
    }
    rotate <-40, 30, 0>                  // lineární transformace aplikovaná na izoplochu
}



// kvádr, do kterého je celá scéna uzavřena
box {
    <-10,-2,-8>, < 10, 10, 8>
    texture {
        pigment {                        // šachovnicová textura
            checker
            color <0.1, 0.3, 0.4>,
            color <0.2, 0.5, 0.7>
        }
        finish {                         // odlesky a odrazy na povrchu
            diffuse 0.7
            reflection 0.2
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1106

Obrázek vytvořený renderingem čtvrtého demonstračního příkladu

7. Použití šumových funkcí

Poměrně zajímavá technika použití implicitních funkcí spočívá v náhradě algebraických a goniometrických funkcí za takzvané šumové funkce. Ty jsou deklarovány v souboru functions.inc, který je dodávaný současně s POV-Rayem. Pro použití šumových funkcí v našich prostorových scénách postačí použít příkaz #include „functions.inc“ a poté již předdefinované funkce využít, například právě při tvorbě izoploch. Šumové funkce jsou většinou prostorové, tj. mají tři parametry představované souřadnicemi x, y a z. Pro každou trojici parametrů volaná šumová funkce vrátí nějakou reálnou hodnotu typicky ležící v rozsahu (0..1). Tato hodnota není zcela náhodná, protože pro body x, y, z, které leží blízko sebe, se budou přibližovat i výsledky šumové funkce a naopak. Tomuto tématu jsem se blíže věnoval v seriálu Fraktály v počítačové grafice, zejména v části věnované Perlinově funkci ( /clanky/perlinova-sumova-funkce-a-jeji-aplikace/). Nám bude stačit znát použití šumových funkcí při tvorbě izoploch, což je ukázáno v následující kapitole.

8. Pátý demonstrační příklad – použití šumových funkcí

V dnešním pátém a současně i posledním demonstračním příkladu si ukážeme použití šumové funkce při tvorbě tělesa, které svojí strukturou připomíná porézní hmotu. Tohoto tvaru je dosaženo za pomocí šumové funkce nazvané f_noise3d, což je mimochodem základní šumová funkce použitá i při tvorbě mnoha typů textur. Hodnota této šumové funkce závisí na všech souřadnicích x, y a z, přičemž výsledek leží v rozsahu (0..1). Vzhledem k tomu, že prahová hodnota (threshold) je nastavena na nulu, je od výsledku šumové funkce odečtena konstanta 0,5, což vlastně změní obor hodnot na rozsah (-0,5..0,5). Změnou této konstanty (od –1 do 0) je možné měnit „hustotu“ tělesa, tj. poměr částí ležících uvnitř tělesa a částí ležících vně (podobného výsledku se samozřejmě dá dosáhnout i změnou prahové hodnoty). Následuje výpis zdrojového kódu tohoto demonstračního příkladu:

// ------------------------------------------------------------
// Pátý demonstrační příklad s izoplochou při jejíž definici
// je použita šumová funkce.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Idemo5.pov +Odemo5.png
// (pro náhled postačí zadat povray demo5.pov)
// ------------------------------------------------------------

#version 3.1;                            // specifikace verze POV-Raye

global_settings {
    assumed_gamma 2.2
}

#include "colors.inc"
#include "woods.inc"
#include "functions.inc"                 // soubor s definicí šumových aj. funkcí

camera {                                 // nastavení kamery,
    right x*image_width/image_height     // které odpovídá optice
    location  <0, 0, -8>                 // lidského oka
    look_at   <0, 0, 0>
    angle 35
}

// první světelný zdroj
light_source {
    <500,500,-500>
    rgb 1
}

// druhý světelný zdroj
light_source {
    <-500,500,-500>
    rgb <0.1,0.1,0.3>
    shadowless
}

// třetí světelný zdroj
light_source {
    <3,3,-3>
    rgb <1,1,1>
    shadowless
}

// povrch plochy
#declare Solid=
texture {                                // vlastnosti materiálu
    pigment {                            // procedurální textura
        agate
        agate_turb 0.7
    }
    finish {                             // odlesky
        phong 1
    }
}

isosurface {                             // izoplocha
    function {
        f_noise3d(2*x, 2*y, 2*z)-0.5
    }
    threshold 0.0                        // prahová hodnota
    accuracy 1e-6                        // přesnost výpočtu
    max_gradient 2                       // maximální gradient (může být i nižší)
    contained_by {                       // těleso, které tvoří hranici izoplochy
        sphere {
            <0,0,0>,2
        }
    }
    texture {
        Solid
    }
    scale 0.9                            // lineární transformace aplikovaná na izoplochu
    rotate <-40, 30, 0>
}



// kvádr, do kterého je celá scéna uzavřena
box {
    <-10,-2,-8>, < 10, 10, 8>
    texture {
        pigment {                        // šachovnicová textura
            checker
            color <0.1, 0.3, 0.4>,
            color <0.2, 0.5, 0.7>
        }
        finish {                         // odlesky a odrazy na povrchu
            diffuse 0.7
            reflection 0.2
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray1107

Obrázek vytvořený renderingem pátého demonstračního příkladu

root_podpora

9. Obsah následující části seriálu

V následující části seriálu o renderovacím programu POV-Ray se budeme zabývat především problematikou osvětlení vytvářených prostorových scén, texturováním povrchu těles (tj. nanášením textur), specifikací optických vlastností materiálu těles a v neposlední řadě také způsobem vykreslení vnitřních částí uzavřených objektů.

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.