Optické vlastnosti průhledných těles

12. 8. 2008
Doba čtení: 13 minut

Sdílet

V dnešní části seriálu o raytraceru POV-Ray se budeme zabývat nastavením dalších optických vlastností materiálů těles využívaných především při výpočtu průhlednosti, lomu světelných paprsků na povrchu těles a v neposlední řadě také simulaci rozkladu světla při průchodu průhlednými tělesy.

Obsah

1. Optické vlastnosti průhledných těles
2. Index lomu
3. První demonstrační příklad – změna indexu lomu
4. Rozklad světla
5. Druhý demonstrační příklad – rozklad světla
6. „Světelná prasátka“
7. Třetí demonstrační příklad – scéna se světelnými prasátky
8. Obsah další části seriálu

1. Optické vlastnosti průhledných těles

V POV-Rayi lze poměrně jednoduchým způsobem vytvořit mnoho vizuálních efektů, které nastávají při průchodu světelných paprsků průhlednými tělesy. V první řadě se jedná o lom světla na rozhraní mezi okolním prostředím a tělesem. Úhel lomu paprsků je ovlivněn především takzvaným indexem lomu, který je možné specifikovat pro každý objekt vložený do vytvářené trojrozměrné scény. Na prvním ilustračním obrázku je zobrazeno několik sklenic s indexem lomu nastaveným na hodnotu 1,5:

povray2401

Obrázek 1: Sklenice, na jejichž povrchu se lámou světelné paprsky

Dále lze simulovat rozklad světelných paprsků, který je možné pozorovat například na průhledných hranolech. Pomocí standardního raytracingu je rozklad světelných paprsků vypočítán sice nepřesně (při lomu se původní paprsek rozpadne na několik paprsků sekundárních, každý bude mít jinak ovlivněnou barvu i úhel lomu), zato však poměrně rychle – viz druhý ilustrační obrázek:

povray2402

Obrázek 2: Simulace rozkladu světelných paprsků pomocí raytracingu

Druhý způsob výpočtu rozkladu světelných paprsků, který je mnohem přesnější a současně i pomalejší, spočívá ve využití dopředného sledování paprsků (photon mapping, direct tracing), což je technika, kterou si popíšeme v některé z následujících částí tohoto seriálu věnovaných pokročilým (a ne příliš známým) možnostem POV-Raye.

povray2403

Obrázek 3: Simulace rozkladu světelných paprsků pomocí photon mappingu

V POV-Rayi je také možné velmi jednoduchým způsobem simulovat vznik světelných „prasátek“, které jsou způsobeny současným odrazem i lomem světla na rozhraní dvou materiálů. Opět se nejedná o fyzikálně zcela přesný výsledek, ovšem vizuální chyby se v tomto případě prakticky nedají nalézt, jelikož se jedná o fenomén vznikající typicky na rozhraní vzduch – voda při zvlněné hladině.

povray2404

Obrázek 4: Netradičním způsobem pojatá vodní hladina

2. Index lomu

Velmi jednoduchým způsobem je možné u průhledných těles specifikovat index lomu. K nastavení všech optických vlastností vnitřků těles slouží uzel nazvaný interior, v němž je pro každé těleso možné změnit hodnotu několika konstant. Jednou z těchto konstant je i index lomu nazvaný krátce ior (index of refraction). Implicitní hodnotou indexu lomu je v POV-Rayi 1,0, což znamená, že k lomu světelných paprsků nedochází (stejný index lomu má totiž i okolní prostředí – vzduchoprázdno). Pro každou hodnotu větší než 1,0 již k lomu světelných paprsků dochází, například voda má index lomu roven 1,33, sklo 1,5 a diamant má velmi vysoký index lomu dosahující hodnoty 2,4. Pokud jsou do sebe vložena dvě tělesa složená z různých průhledných materiálů, bude úhel lomu světelných paprsků odvozen z indexů lomů obou materiálů. Například sklo ponořené do vody bude světlo lámat jinak než sklo ve vzduchu; tento jev si každý může ověřit při potápění. Poznamenejme, že index lomu je odvozen od poměru rychlosti šíření světla ve vakuu a daném materiálu.

povray2405

Obrázek 5: Skleněný objekt vymodelovaný pomocí implicitních ploch (metaballs)

3. První demonstrační příklad – změna indexu lomu

V dnešním prvním demonstračním příkladu je vytvořeno pět průhledných objektů, přičemž každému objektu je přiřazen jiný index lomu. První objekt (umístěný na levé straně obrázku) má index lomu diamantu (ior=2,4), další dva objekty jsou vytvořeny z různých typů skel, čtvrtý objekt je vymodelován z vody a konečně poslední objekt (umístěný zcela vpravo) má index lomu nastavený na 1,000292, což je index lomu vzduchu. Aby byl vliv indexů lomů více patrný, je za každým průhledným objektem umístěna oranžová koule: celkem se tedy ve scéně nachází pět různých průhledných objektů a pět naprosto stejných oranžových koulí. Povšimněte si, že zatímco u prvních čtyř objektů jejich kulaté části fungují jako čočka, poslední objekt sice také lomí světelné paprsky, ale ve zcela zanedbatelné míře (index lomu vzduchu je prakticky stejný jako index lomu vzduchoprázdna). Lom je u tohoto objektu patrný pouze na textuře podlahy.

povray2406

Obrázek 6: První demonstrační příklad po vykreslení v POV-Rayi

Následuje výpis zdrojového kódu prvního demonstračního příkladu:

// ------------------------------------------------------------
// První demonstrační příklad založený na zdrojovém souboru
// dodávaném společně s POV-Rayem.
//
// Ukázka lomu světelných paprsků na tělesech vytvořených
// z různých typů skel.
// ------------------------------------------------------------

global_settings {
    max_trace_level 20                   // maximální počet odrazů/lomů
    assumed_gamma 2.2
}

#include "colors.inc"
#include "shapes.inc"
#include "textures.inc"
#include "glass.inc"
#include "consts.inc"                    // obsahuje mj. i indexy lomu

camera {
    location  <0, 5, -20>                // pozice kamery v prostoru
    direction z                          // směr kamery
    angle    57                          // zorný úhel
    up       <0.0, 1.0, 0.0>             // vektor směřující vzhůru (část orientace kamery v prostoru)
    right    <4/3, 0.0, 0.0>             // vektor směřující doprava
    look_at  <0, 1, 0>
}

// barva jednoho světelného zdroje
#declare Watts = color Gray25;
#declare Light_Distance = -50;

// několik světelných zdrojů sdružených do jednoho objektu
union {
    light_source  { <-6, 0, Light_Distance>  color Watts  }
    light_source  { <-4, 0, Light_Distance>  color Watts  }
    light_source  { <-2, 0, Light_Distance>  color Watts  }
    light_source  { < 0, 0, Light_Distance>  color Watts  }
    light_source  { < 2, 0, Light_Distance>  color Watts  }
    light_source  { < 4, 0, Light_Distance>  color Watts  }
    light_source  { < 6, 0, Light_Distance>  color Watts  }

    rotate 60*x

    pigment { White }                    // nemá žádný vliv na výsledek, jen pro zabránění warningu
}


// podlaha
plane {
    y, -1                                // orientace a vzdálenost od středu
    pigment {
        checker color HuntersGreen color SummerSky
        scale <32000, 1, 2>
    }
    finish {
        ambient 0.1
        diffuse 0.6
    }
}


// objekt, na kterém se bude zkoumat vliv indexu lomu
// skládá se z průhledné části a oranžové koule
#declare Hummer =
union {
    // skleněná část objektu
    union {
        object { UnitBox }
        object { Disk_Y translate 2*y }
        sphere { <0, 4, 0>, 1 }
        rotate 45*y
    }

    // oranžová koule umístěná za skleněnou částí
    sphere { <0, 5, 20>, 1
        texture {
            finish { Shiny }
            pigment { Orange }
        }
     }
}

// textura, která je přiřazena všem následujícím objektům
default { texture { T_Glass1 } }


// vložení všech pěti objektů do scény, každý objekt má jiný index lomu
object {
    Hummer
    translate -6*x
    interior {
        ior Diamond_Ior
    }
}

object {
    Hummer
    translate -3*x
    interior {
        ior Flint_Glass_Ior
    }
}

object {
    Hummer
    translate 0*x
    interior {
        ior Crown_Glass_Ior
    }
}

object {
    Hummer
    translate 3*x
    interior {
        ior Water_Ior
    }
}

object {
    Hummer
    translate 6*x
    interior {
        ior Air_Ior
    }
}

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 

4. Rozklad světla

S lomem světelných paprsků souvisí i jejich rozklad, který je možné pozorovat na krystalech vyrobených z materiálů, které mají vysoký index lomu (diamant a další drahokamy). V POV-Rayi lze rozklad světla simulovat buď pomocí klasického raytracingu, konkrétně nastavením atributu dispersion, nebo dopředným sledováním paprsků, které je sice mnohem pomalejší, na druhou stranu však produkuje přesnější výsledky. Dnes si popíšeme první možnost. V uzlu interior je možné specifikovat hodnotu atributu dispersion, která udává míru rozkladu světla na jednotlivé barvy duhy. Implicitní hodnota tohoto atributu je 1,0, což znamená, že k rozkladu nedochází. Dále je možné nastavit atribut dispersion_sam­ples, jehož (celočíselná) hodnota ovlivňuje počet generovaných sekundárních paprsků – každý paprsek představuje jednu barvu z celého spektra. Čím vyšší je hodnota tohoto atributu, tím přesnější bude výsledek (přechody mezi barvami budou plynulé), ovšem zvýší se i doba potřebná pro výpočet.

povray2407

Obrázek 7: Okolo odlesků diamantu je patrný rozklad světla

Jednoduchý rozklad světla lze vytvořit i na kouli, což je ukázáno v následujícím fragmentu kódu:

// globální nastavení parametrů scény
global_settings {
    assumed_gamma 2.2
    max_trace_level 5
}

// načtení všech potřebných externích souborů
#include "colors.inc"
#include "stones.inc"
#include "glass.inc"

// nastavení kamery (pozorovatele)
camera {
    location  <1.65, 5.5, -5.0>          // pozice kamery
    up        <0.0,  1.0,  0.0>          // vektor směřující vzhůru
    right     <4/3,  0.0,  0.0>          // vektor směřující doprava
    look_at   <0,    0.5, -1.0>          // bod, na který kamera směřuje
}

// tři světelné zdroje
light_source {
    <-30, 11,  20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 31, 12, -20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 32, 11, -20>                       // pozice světelného zdroje
    color LightGray                      // barva světla
}

// jediný uzavřený objekt ve scéně - skleněná koule
sphere {
    <0, 0, 0>,                           // souřadnice středu koule
    1.75                                 // poloměr koule
    interior {                           // vlastnosti "vnitřku" koule
        caustics 1.0
        ior 1.5
        dispersion 1.1
        dispersion_samples 50
    }
    texture {                            // textura - povrch koule
        T_Glass1                         // definováno v externím souboru
        pigment {
            color red 0.90 green 0.90 blue 0.90 filter 0.85 // barva povrchu
        }
        finish {                         // optické vlastnosti materiálu
            phong 1                      // velikost a síla odlesků
            phong_size 300
            reflection 0.15              // odrazivost
        }
    }
}

// druhý objekt - nekonečná rovina
plane {
    y,                                   // orientace roviny
    -1.5                                 // vzdálenost od počátku
    texture {                            // textura - vlastnosti povrchu
        T_Stone1                         // definováno v externím souboru
        pigment {                        // vlastní vzorek textury
            octaves 3                    // modifikace procedurálního vzorku
            rotate 90*z
        }
        finish {                         // optické vlastnosti materiálu
            reflection 0.10
        }
    }
} 

5. Druhý demonstrační příklad – rozklad světla

Ve druhém demonstračním příkladu je ukázán rozklad světla na objektech různých tvarů. Jedná se o superelipsoidy (viz pátá část tohoto seriálu), které jsou vyrobeny z průhledného materiálu s indexem lomu nastaveným na hodnotu 1,4, tj. jedná se o materiál s vlastnostmi skla (sami si můžete vyzkoušet, jak bude scéna vypadat při nastavení indexu lomu na hodnotu 2,4, což odpovídá diamantu). Také míra rozkladu světla je nastavena na hodnotu 1,4, což vede k tomu, že se na hranách těles vytváří duhové odlesky. U některých objektů je patrné, že je světlo rozloženo jen do několika barev, protože implicitní hodnota atributu dispersion_sam­ples je rovna pouze sedmi, tj. po dopadu na povrch tělesa se původní paprsek rozloží na sedm sekundárních paprsků, z nichž každý má nastavený odlišný barevný filtr. Zdrojový kód druhého demonstračního příkladu má tvar:

// ------------------------------------------------------------
// Druhý demonstrační příklad - rozklad světla na objektech
// různých tvarů.
// Několik superelipsoidů odvozených od základního tvaru krychle.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Isuper2.pov +Osuper2.png
// (pro náhled postačí zadat povray super2.pov)
// ------------------------------------------------------------

global_settings {
    assumed_gamma 2.2
}

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 0.7 green 0.7 blue 0.7     // barva světelného zdroje
}

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

plane {                                  // rovina tvořící pozadí scény
    <0, 0, 1>, 3                         // posun a orientace roviny
    hollow on
    texture {pigment {color red 1.0 green 1.0 blue 1.0}}
    finish {                             // optické vlastnosti materiálu povrchu
        ambient 0.1
        diffuse 0.4
    }
}

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

// textura všech objektů
#declare Tex =
texture {
    pigment {
        color red 1 green 1 blue 1 filter 0.8
    }
    finish {
        ambient 0.2 diffuse 0.4 phong 0.5 phong_size 5
    }
}

// následují jednotlivé superelipsoidy

superellipsoid {
    <0.0, 0.1> scale 1.6 rotate <-15, 30, 0> translate <Col1, Row1, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 0.2> scale 1.6 rotate <-15, 30, 0> translate <Col2, Row1, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 0.3> scale 1.6 rotate <-15, 30, 0> translate <Col3, Row1, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 0.8> scale 1.6 rotate <-15, 30, 0> translate <Col4, Row1, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 1.0> scale 1.6 rotate <-15, 30, 0> translate <Col5, Row1, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 1.5> scale 1.6 rotate <-15, 30, 0> translate <Col1, Row2, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 2.0> scale 1.6 rotate <-15, 30, 0> translate <Col2, Row2, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 2.5> scale 1.6 rotate <-15, 30, 0> translate <Col3, Row2, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 3.0> scale 1.6 rotate <-15, 30, 0> translate <Col4, Row2, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <0.0, 4.0> scale 1.6 rotate <-15, 30, 0> translate <Col5, Row2, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 0.1> scale 1.6 rotate <-15, 30, 0> translate <Col1, Row4, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 0.2> scale 1.6 rotate <-15, 30, 0> translate <Col2, Row4, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 0.3> scale 1.6 rotate <-15, 30, 0> translate <Col3, Row4, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 0.8> scale 1.6 rotate <-15, 30, 0> translate <Col4, Row4, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 1.0> scale 1.6 rotate <-15, 30, 0> translate <Col5, Row4, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 1.5> scale 1.6 rotate <-15, 30, 0> translate <Col1, Row5, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 2.0> scale 1.6 rotate <-15, 30, 0> translate <Col2, Row5, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 2.5> scale 1.6 rotate <-15, 30, 0> translate <Col3, Row5, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 3.0> scale 1.6 rotate <-15, 30, 0> translate <Col4, Row5, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}

superellipsoid {
    <2.0, 4.0> scale 1.6 rotate <-15, 30, 0> translate <Col5, Row5, 0>
    texture { Tex }
    interior { ior 1.4 dispersion 1.4 }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray2408

Obrázek 8: Druhý demonstrační příklad po vykreslení v POV-Rayi

6. „Světelná prasátka“

Současným odrazem i lomem světla na rozhraní dvou prostředí může docházet ke vzniku „světelných prasátek“ (caustics). Tohoto zajímavého světelného efektu je možné v POV-Rayi dosáhnout poměrně jednoduše – postačí v uzlu interior nastavit hodnotu atributu caustics na nenulovou hodnotu. Tento atribut typicky nabývá hodnot z rozsahu nula až jedna, ovšem je možné specifikovat i hodnoty větší než jednička. Implicitně je nastavena nulová hodnota, což tvorbu světelných prasátek zakáže a vykreslení celé scény se nepatrně zrychlí (ne však do takové míry, jako vypnutí rozkladu světla, to je výpočetně mnohem náročnější). Malé hodnoty atributu, které se pohybují v blízkosti nuly, vedou ke vzniku rozsáhlejších světlých ploch, zatímco hodnoty vyšší (jedna a více) způsobí vznik menších, ale zato výraznějších světelných prasátek. Důležité je nastavit atribut caustics u objektu, který má prasátka vrhat a ne u objektu, na kterém se zviditelňují.

povray2409

Obrázek 9: Světelná prasátka vrhaná skleněnými objekty

7. Třetí demonstrační příklad – scéna se světelnými prasátky

V dnešním třetím demonstračním příkladu je ukázáno použití světelných prasátek, které mohou výrazně obohatit i scénu složenou z malého množství objektů. Testovací scéna má představovat pohled pod hladinou bazénu. Ve své jednodušší podobě se ve scéně nachází pouze dva objekty – dno bazénu a vodní hladina; v podobě složitější jsou pak ještě přidány stěny bazénu vymodelované pomocí jediného kvádru s nanesenou šachovnicovou texturou. Tvorba světelných prasátek je povolena a současně i nastavena při definici vodní hladiny. Kromě barvy hladiny je povoleno i modulování normálových vektorů (bump mapping), pro nějž je použita procedurální textura bumps. To spolu s nastaveným indexem lomu vody (ior 1.1) vede k nepravidelnému lomu paprsků na povrchu vodní hladiny, protože se při výpočtu lomeného paprsku vychází z orientace normálového vektoru, který je procedurální texturou modulován. Modifikátorem caustics 1.0 umístěným uvnitř uzlu interior je pak definována míra tvorby prasátek na dně bazénu a částečně i na jeho stěnách.

povray2410

Obrázek 10: Třetí demonstrační příklad po vykreslení v POV-Rayi (do scény jsou zahrnuty i stěny bazénu)

Zdrojový kód třetího demonstračního příklad má tvar:

// ------------------------------------------------------------
// Třetí demonstrační příklad - vytvoření "prasátek" na dně
// bazénu vzniklých vlnkami na vodní hladině.
//
// rendering lze spustit poíkazem:
//     povray +W800 +H600 +B100 +FN +D +Icaustic.pov +Ocaustic.png
// (pro náhled postaeí zadat povray caustic.pov)
// ------------------------------------------------------------

global_settings {
    assumed_gamma 2.2
}

#include "colors.inc"
#include "textures.inc"

camera {                                 // nastavení kamery
    direction z                          // směr pohledu kamery
    location <0, 6, -15>                 // umístění kamery
    look_at <0, 2, 0>                    // bod, na který se kamera zaměřila
}

light_source {                           // nastavení světelného zdroje
    <0, 50, 0>                           // pozice světelného zdroje
    color White                          // barva světelného zdroje
}

plane {                                  // dno bazénu
    y, 0                                 // orientace roviny a její posun od počátku
    pigment {                            // barva dna
        Gray60
    }
    finish {                             // vypnutí odlesků
        ambient 0.1
        diffuse 0.7
    }
}

// kvádr, do kterého je celá scéna uzavoena
/*
box {
    <-10,-16,-16>, < 10, 200, 10>
    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                  // kvádru
            reflection 0.1
            ambient 0.1
        }
    }
}
*/

plane {                                  // vodní hladina
    y, 10                                // orientace roviny a její posun od počátku
    hollow on                            // jedná se o "prázdný" objekt, nikoli poloprostor
    pigment {                            // barva hladiny
        red 0.7 green 0.7 blue 1.0 filter 0.9
    }
    finish {                             // odrazivost
        reflection 0.7
    }
    interior {
        ior 1.1                          // index lomu vody
        caustics 1.0                     // povolení "prasátek"
    }
    translate <5, 0, -10>                // lineární transformace
    normal {                             // vlny
        bumps 0.5
    }
}

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray2411

Obrázek 11: Třetí demonstrační příklad po vykreslení v POV-Rayi (stěny bazénu nejsou do scény zahrnuty)

bitcoin školení listopad 24

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

V následujícím pokračování seriálu o raytraceru POV-Ray si řekneme, jakým způsobem je pro něj možné vytvářet scény. Popíšeme si především některé volně dostupné modelovací programy, které je možné spolu s POV-Rayem využít, ale i další specializované nástroje, například generátory krajiny (terénu), generátory keřů a stromů, programy pro konverzi trojrozměrných dat z různých formátů do jazyka POV-Raye apod.

povray2412

Obrázek 12: KPovRay modeller patří mezi celou řadu modelovacích programů, které dokáží vytvořit popis scén zpracovatelný POV-Rayem

Autor článku

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