Hlavní navigace

Tvorba plasmy alternativními metodami

19. 9. 2006
Doba čtení: 14 minut

Sdílet

V dnešním pokračování seriálu, ve kterém popisujeme fraktály, si ukážeme další možnosti tvorby krajiny (terénu) pomocí dvourozměrných obrázků plasmy. Kromě vysvětlení jedné zajímavé alternativní metody výpočtu plasmy si ukážeme tvorbu barevné plasmy s využitím palety i plnobarevného (truecolor) režimu.

Obsah

1. Alternativní metoda generování plasmy
2. První demonstrační příklad – implementace alternativní metody generování plasmy
3. Vytvoření plasmy s pomocí barvové palety
4. Druhý demonstrační příklad – použití barvové palety
5. Vytvoření plnobarevné plasmy
6. Třetí demonstrační příklad – plnobarevná plasma
7. Obsah dalšího pokračování tohoto seriálu

1. Alternativní metoda generování plasmy

V předchozí části tohoto seriálu jsme si vysvětlili a také prakticky ukázali metodu rekurzivního dělení čtverce s posunem prostředního bodu (Midpoint Displacement Method). Pomocí této metody je možné vytvářet působivé obrázky plasmy; pro některé vstupní parametry však mohou být na obrázcích patrné vodorovné a svislé přechody mezi barvami, které tvoří hranice mezi čtverci na několika nejvyšších úrovních dělení. Na nižších úrovních, cca od čtvrté iterace, hranice splývají, neboť dochází ke snižování „amplitudy“ odchylky Δ.

Opticky rušivé přechody vznikají z toho důvodu, že se při každém rozdělení čtverce posune pouze jeho prostřední bod (střed) a nikoli prostřední body jeho hran – pro jejich posun nemáme dostatek informací, protože nevíme, jakým způsobem budou rozděleny čtyři sousední čtverce. Na prvním ilustračním obrázku je zobrazena plasma vygenerovaná pomocí demonstračního příkladu uvedeného minule, druhý obrázek ukazuje tu stejnou plasmu s nakreslenými hranicemi mezi čtverci vzniklými při první (červené úsečky) a druhé (modré úsečky) iteraci.

fractals47_1

Obrázek 1: Plasma vytvořená metodou rekurzivního dělení čtverce

fractals47_2

Obrázek 2: Hranice mezi čtverci vzniklými při první a druhé iteraci

Existuje několik způsobů, jak nežádoucí přechody odstranit. Některé způsoby spočívají v odlišném dělení čtverce, například střídavě po úhlopříčkách a vodorovných/svis­lých hranách, jiné způsoby zavádí „paměť“ posuvu prostředních bodů okolních čtverců apod.

My si však ukážeme zajímavější (a poněkud neznámou) alternativní metodu, která už nespočívá v rekurzivním dělení čtverce. Princip této alternativní metody spočívá v iterativním generování různě orientovaných přímek, které rozdělují obraz na dvě (obecně) nestejně velké poloviny. Po vygenerování náhodné přímky (ta po protnutí hranic obrázku vytvoří úsečku) se provedou následující operace:

  1. Intenzita všech pixelů ležících nalevo od přímky se sníží o jedničku.
  2. Intenzita všech pixelů ležících napravo od přímky se naopak o jedničku zvýší.

Pro vytvoření plasmy je zapotřebí vytvoření přímky a snižování/zvyšování intenzity pixelů provádět ve smyčce mnohokrát, typická hodnota bývá 1 000 – 10 000 iterací. Po provedení takto vysokého množství iterací již hranice mezi různě orientovanými přímkami nejsou patrné. Po provedení všech iterací je nutné obrázek normalizovat, tj. nejnižší intenzitě pixelů (ta může být díky odčítání i záporná) přiřadit černou barvu a nejvyšší intenzitě barvu čistě bílou. Výsledkem těchto operací je plasma zobrazená na třetím obrázku.

fractals47_3

Obrázek 3: Plasma vytvořená alternativní metodou – generováním náhodných přímek a změnou intenzit pixelů

Na čtvrtém obrázku je v animaci ukázáno, jakým způsobem se mění charakter plasmy s přibývajícím množstvím iterací. Jak je z animace patrné, při malém množství iterací jsou viditelné jednotlivé poloroviny (které definují přímky), ale s rostoucím množstvím iterací se hranice mezi polorovinami rozplývají. V případě požadavků na další vyhlazení obrázku je samozřejmě možné použít konvoluční filtry, jež jsou implementované v prakticky každém pokročilejším grafickém editoru (GIMP, Photoshop, Corel Painter aj.).

fractals47_4

Obrázek 4: Animace vlivu počtu iterací na tvar plasmy

2. První demonstrační příklad – implementace alternativní metody generování plasmy

V dnešním prvním demonstračním příkladu je implementována alternativní metoda generování plasmy. Samotná plasma je vytvářena ve funkci recalcFractal(), která má tvar:

//-----------------------------------------------------------------------------
// Překreslení fraktální plasmy
//-----------------------------------------------------------------------------
void recalcFractal(void)
{
    int bitmap[PIXMAP_HEIGHT][PIXMAP_WIDTH];
    int i, x, y;
    int min=INT_MAX, max=0;                 // pro změnu kontrastu bitmapy
    float fmin=1e10, fmax=-1e10;            // pro přepočet intenzit pixelů
    int x1, y1, x2, y2;                     // souřadnice generovaných bodů

    srand(123456);
    for (y=0; y<PIXMAP_HEIGHT; y++)         // vymazání pracovní bitmapy
        for (x=0; x<PIXMAP_WIDTH; x++)
            bitmap[y][x]=0;

    for (i=0; i<maxiter; i++) {             // iterační smyčka
        x1=rand()%PIXMAP_WIDTH;
        y1=0;
        x2=rand()%PIXMAP_WIDTH;
        y2=PIXMAP_HEIGHT-1;
        addHalfPlane(bitmap, x1, y1, x2, y2);// úsečka z horního k dolnímu okraji
        x1=0;
        y1=rand()%PIXMAP_HEIGHT;
        x2=PIXMAP_WIDTH-1;
        y2=rand()%PIXMAP_HEIGHT;
        addHalfPlane(bitmap, x1, y1, x2, y2);// úsečka z levého k pravému okraji
        if (!(i%100)) printf("%i\t", i);
    }

    // oprava intenzity rohového pixelu
    bitmap[PIXMAP_HEIGHT-1][PIXMAP_WIDTH-1]=bitmap[PIXMAP_HEIGHT-2][PIXMAP_WIDTH-2];

    // získání statistiky o obrázku
    for (y=0; y<PIXMAP_HEIGHT; y++)
        for (x=0; x<PIXMAP_WIDTH; x++) {
            if (max<bitmap[y][x]) max=bitmap[y][x];
            if (min>bitmap[y][x]) min=bitmap[y][x];
        }
    printf("min=%d\nmax=%d\n", min, max);

    // změna kontrastu a kopie bitmapy
    for (y=0; y<PIXMAP_HEIGHT; y++)
        for (x=0; x<PIXMAP_WIDTH; x++) {
            float f=bitmap[y][x];
            f-=min;
            f*=255.0/(max-min);
            if (fmin>f) fmin=f;
            if (fmax<f) fmax=f;
            putpixel(pix, x, y, (int)f, (int)f, (int)f);
        }
    printf("fmin=%f\nfmax=%f\n", fmin, fmax);
} 

V této funkci se postupně mění intenzity pixelů v pomocné pracovní bitmapě. Nejprve je bitmapa vymazána a posléze se v iterační smyčce generují dva typy přímek: přímky spojující pravý a levý okraj bitmapy a přímky spojující její horní a spodní okraj. To sice není zcela korektní, protože ne všechny orientace (směrnice) úseček mají stejnou pravděpodobnost, jedná se však o nejjednodušší řešení. Pro každou takto vygenerovanou úsečku je zavolána funkce addHalfPlane(), ve které je implementován modifikovaný Bresenhamův algoritmus rasterizace úsečky:

//-----------------------------------------------------------------------------
// Přidání poloroviny do pracovní bitmapy pomocí modifikovaného Bresenhamova
// algoritmu pro rasterizaci úsečky
//-----------------------------------------------------------------------------
void addHalfPlane(int bitmap[PIXMAP_HEIGHT][PIXMAP_WIDTH], int x1, int y1, int x2, int y2)
{
    int x, y;
    int i, j, deltax, deltay, numpixels;
    int d, dinc1, dinc2, xinc1, xinc2, yinc1, yinc2;
    int dir;

    dir=rand()%2;                           // směr "kladné" a "záporné" poloroviny

    // otestovat mezní stavy
    if (x1<0 || x2<0 || y1<0 || y2<0) return;
    if (x1>=PIXMAP_WIDTH || x2>=PIXMAP_WIDTH || y1>=PIXMAP_HEIGHT || y2>=PIXMAP_HEIGHT) return;

    deltax=abs(x2-x1);                      // použito pro predikci v Bresenhamově algoritmu
    deltay=abs(y2-y1);

    if (deltax>=deltay) {                   // úhel je menší než +-45 stupňů
        numpixels=deltax;                   // celkový počet pixelů na úsečce
        d=(deltay<<1)-deltax;               // predikce
        dinc1=deltay<<1;                    // změna predikce v každém kroku
        dinc2=(deltay-deltax)<<1;
        xinc1=xinc2=1;
        yinc1=0;
        yinc2=1;
    }
    else {                                  // úhel je větší než +-45 stupňů
        numpixels=deltay;                   // celkový počet pixelů na úsečce
        d=(deltax<<1)-deltay;               // predikce
        dinc1=deltax<<1;                    // změna predikce v každém kroku
        dinc2=(deltax-deltay)<<1;
        xinc1=0;
        yinc1=yinc2=1;
        xinc2=1;
    }
    if (x2<x1) {                            // opačná orientace úsečky:
        xinc1=-xinc1;                       // prohození x-ových souřadnic
        xinc2=-xinc2;
    }
    if (y2<y1) {                            // opačná orientace úsečky:
        yinc1=-yinc1;                       // prohození y-ových souřadnic
        yinc2=-yinc2;
    }
    x=x1;                                   // nastavení počátečního pixelu
    y=y1;
    for (i=0; i<numpixels; i++) {           // pro všechny pixely na úsečce
        if (deltax>=deltay) {               // méně než 45 stupňů - vertikální čáry
            if (dir) {
                for (j=0; j<=y; j++)
                    bitmap[j][x]--;         // snížení intenzity pixelu
                for (j=y; j<PIXMAP_HEIGHT; j++)
                    bitmap[j][x]++;         // zvýšení intenzity pixelu
            }
            else {
                for (j=0; j<=y; j++)
                    bitmap[j][x]++;         // zvýšení intenzity pixelu
                for (j=y; j<PIXMAP_HEIGHT; j++)
                    bitmap[j][x]--;         // snížení intenzity pixelu
            }
        }
        else {                              // více než 45 stupňů - horizontální čáry
            if (dir) {
                for (j=0; j<=x; j++)
                    bitmap[y][j]--;         // snížení intenzity pixelu
                for (j=x; j<PIXMAP_WIDTH; j++)
                    bitmap[y][j]++;         // zvýšení intenzity pixelu
            }
            else {
                for (j=0; j<=x; j++)
                    bitmap[y][j]++;         // zvýšení intenzity pixelu
                for (j=x; j<PIXMAP_WIDTH; j++)
                    bitmap[y][j]--;         // snížení intenzity pixelu
            }
        }
        if (d<0) {                          // posun na další pixel
            d+=dinc1;                       // podle predikce
            x+=xinc1;
            y+=yinc1;
        }
        else {
            d+=dinc2;
            x+=xinc2;
            y+=yinc2;
        }
    }
} 

fractals47_5

Obrázek 5: Screenshot prvního demonstračního příkladu

Modifikace Bresenhamova algoritmu spočívá v tom, že vypočtené body na úsečce nejsou přímo vykreslovány, nýbrž tvoří hranici mezi pixely, u nichž se má intenzita snížit a pixely, u nichž se intenzita naopak zvyšuje. Před vykreslením bitmapy je zapotřebí provést její normalizaci. Ta je rozdělena do dvou smyček. V první smyčce se zjistí minimální a maximální intenzity pixelů, ve druhé smyčce jsou tyto intenzity použity ve vzorci, který provádí normalizaci, tj. převod pixelů do rozsahu 0..255.

Zdrojový kód prvního demonstračního příkladu je dostupný jak ve formě zdrojového textu, tak i jako HTML stránka s obarvenou syntaxí. Změnou konstanty maxiter pomocí kláves [0][9] je možné ovlivnit celkový počet iterací (generovaných úseček) a tím i detaily ve výsledné plasmě. Klávesou [S] se uloží obrázek plasmy na disk, klávesa [Space] slouží k přepočtu plasmy a konečně klávesa [Q] či [Esc] demonstrační příklad ukončí.

fractals47_6

Obrázek 6: Obrázek vytvořený v prvním demonstračním příkladu po úpravě Gaussovým filtrem

3. Vytvoření plasmy s pomocí barvové palety

Oba poslední demonstrační příklady (jeden prezentovaný minule, druhý v předchozí kapitole) slouží k vytváření obrázků, ve kterých je plasma vygenerovaná ve stupních šedi. Pro některé použití, například pokud plasma tvoří vstup pro generování trojrozměrného terénu, není tento fakt na škodu, avšak při přímém zobrazování plasmy většinou budeme vyžadovat barevné obrázky. Existuje prakticky nepřeberné množství metod pro „obarvení“ plasmy. V této kapitole si uvedeme pravděpodobně nejpoužívanější metodu, která využívá barvovou paletu.

fractals47_7

Obrázek 7: Plasma s barvovou paletou

Použití barvové palety je velmi jednoduché a přímočaré. Podobně jako v předchozí metodě jsou intenzity všech pixelů nejprve převedeny do předem zadaného intervalu celých čísel, typicky 0..255. Poté je provedeno přemapování těchto hodnot na barvy pomocí barvové palety. Ta musí obsahovat počet řádků odpovídající zvolenému intervalu. Samotné mapování barev se provádí po normalizaci bitmapy, tj. po provedení operace, která zaručí, že všechny pixely mají hodnoty ležící v zadaném intervalu. Posléze se pro každý pixel nalezne barva v barvové paletě a ta je pixelu přiřazena.

4. Druhý demonstrační příklad – použití barvové palety

Dnešní druhý demonstrační příklad je prakticky totožný s příkladem prvním, jsou v něm totiž implementovány pouze dvě změny. Přibyla funkce mapPalette(), která pro zadaný index v rozsahu 0..255 a číslo palety v rozsahu 0..9 vrátí trojici hodnot R, G, B, kterou je možné použít pro obarvení pixelů. Dále byla změněna funkce recalcFractal(), konkrétně poslední smyčka, ve které se prováděla normalizace bitmapy, tj. přepočet všech pixelů tak, aby měly intenzitu 0..255. Ve druhém příkladě je vypočtená intenzita použita jako index do barvové palety, takže ve výsledku dojde k vytvoření obrázku s libovolnými 256 (28) barvami.

fractals47_8

Obrázek 8: Screenshot druhého demonstračního příkladu

Upravená funkce recalcFractal() má tvar:

//-----------------------------------------------------------------------------
// Překreslení fraktální plasmy
//-----------------------------------------------------------------------------
void recalcFractal(void)
{
    int bitmap[PIXMAP_HEIGHT][PIXMAP_WIDTH];
    int i, x, y;
    int min=INT_MAX, max=0;                 // pro změnu kontrastu bitmapy
    float fmin=1e10, fmax=-1e10;            // pro přepočet intenzit pixelů
    int x1, y1, x2, y2;                     // souřadnice generovaných bodů

    srand(123456);
    for (y=0; y<PIXMAP_HEIGHT; y++)         // vymazání pracovní bitmapy
        for (x=0; x<PIXMAP_WIDTH; x++)
            bitmap[y][x]=0;

    for (i=0; i<maxiter; i++) {             // iterační smyčka
        x1=rand()%PIXMAP_WIDTH;
        y1=0;
        x2=rand()%PIXMAP_WIDTH;
        y2=PIXMAP_HEIGHT-1;
        addHalfPlane(bitmap, x1, y1, x2, y2);// úsečka z horního k dolnímu okraji
        x1=0;
        y1=rand()%PIXMAP_HEIGHT;
        x2=PIXMAP_WIDTH-1;
        y2=rand()%PIXMAP_HEIGHT;
        addHalfPlane(bitmap, x1, y1, x2, y2);// úsečka z levého k pravému okraji
        if (!(i%100)) printf("%i\t", i);
    }

    // oprava intenzity rohového pixelu
    bitmap[PIXMAP_HEIGHT-1][PIXMAP_WIDTH-1]=bitmap[PIXMAP_HEIGHT-2][PIXMAP_WIDTH-2];

    // získání statistiky o obrázku
    for (y=0; y<PIXMAP_HEIGHT; y++)
        for (x=0; x<PIXMAP_WIDTH; x++) {
            if (max<bitmap[y][x]) max=bitmap[y][x];
            if (min>bitmap[y][x]) min=bitmap[y][x];
        }
    printf("min=%d\nmax=%d\n", min, max);

    // změna kontrastu a kopie bitmapy
    for (y=0; y<PIXMAP_HEIGHT; y++)
        for (x=0; x<PIXMAP_WIDTH; x++) {
            char r,g,b;                      // barvové složky R, G, B
            float f=bitmap[y][x];
            f-=min;
            f*=255.0/(max-min);
            if (fmin>f) fmin=f;
            if (fmax<f) fmax=f;
            mapPalette(palette, (int)f, &r, &g, &b); // mapování barvové palety
            putpixel(pix, x, y, r, g, b);    // uložení pixelu
        }
    printf("fmin=%f\nfmax=%f\n", fmin, fmax);
} 

Zdrojový kód druhého demonstračního příkladu je dostupný jak ve formě zdrojového textu, tak i jako HTML stránka s obarvenou syntaxí. Ovládání tohoto demonstračního příkladu se podobá příkladu předchozímu, ovšem s tím rozdílem, že se klávesami [0][9] nemění maximální počet iterací, ale použitá barvová paleta.

fractals47_9

Obrázek 9: Obrázek vytvořený ve druhém demonstračním příkladu po provedení detekce hran

5. Vytvoření plnobarevné plasmy

Dalším způsobem vykreslení barevné plasmy je – kromě výše zmíněného použití barvové palety – výpočet plnobarevné (truecolor) plasmy. Ve skutečnosti se nejedná o nic jiného než o výpočet tří navzájem nesouvisejících obrázků, kde každý obrázek nese informace o intenzitě jedné barvové složky (obrázky mají společné pouze rozlišení). Podle použitého barvového modelu se může jednat o obrázky se složkami HSV (Hue–Saturation–Value), HLS (Hue–Lightness–Saturation), CMY (Cyan–Magenta–Yellow) či RGB (Red–Green–Blue). Z implementačního hlediska je nejjednodušší použití barvového modelu RGB, který je podporován prakticky ve všech grafických knihovnách, avšak pro dosažení zajímavých barvových efektů je možné použít i jiný barvový model, například HLS, ve kterém jeden obrázek ovlivňuje barevný tón, druhý obrázek světlost barvy a třetí obrázek její sytost. Příklad implementace výpočtu barevné palety je ukázán v dnešním třetím demonstračním příkladu.

fractals47_a

Obrázek 10: Plnobarevná plasma vytvořená ve třetím demonstračním příkladu

6. Třetí demonstrační příklad – plnobarevná plasma

V dnešním třetím a současně i posledním demonstračním příkladu je ukázána jedna z možných variant vytváření plnobarevné plasmy. Oproti prvnímu demonstračnímu příkladu došlo ke změně pouze ve funkci recalcFractal(). Změna spočívá v rozšíření pracovní bitmapy bitmap o další dvě barvové roviny. Pro každou barvovou rovinu je proveden samostatný výpočet plasmy s obecně jinými náhodnými hodnotami, všechny tři obrázky jsou tedy od sebe odlišné, což se dá jednoduše dokázat například rozložením výsledného obrázku do jednotlivých kanálů v grafickém editoru (GIMP apod.).

Po vygenerování všech tří obrázků je každý z nich (opět samostatně) normalizován, tj. je upravena intenzita všech pixelů tak, aby jejich hodnota nabývala hodnot z rozsahu 0..255. Teprve poté je provedeno sloučení obrázků a vykreslení barevných pixelů pomocí funkce putpixel do výsledné pixmapy, která je posléze zobrazena v okně aplikace.

Pokud navzájem porovnáme funkce recalcFractal() z prvního a třetího demonstračního příkladu, zjistíme, že kromě rozšíření některých skalárních proměnných na pole a přidání tří smyček, jsou obě funkce totožné. Změnu barvového modelu je možné provést jednoduše nahrazením funkce putpixel() za funkci provádějící přepočet z daného barvového modelu do modelu RGB, který je implicitně použit v grafické knihovně OpenGL.

fractals47_b

Obrázek 11: Obrázek vzniklý po spuštění třetího demonstračního příkladu

Pozměněná funkce recalcFractal() má tvar:

//-----------------------------------------------------------------------------
// Překreslení fraktální plasmy v truecolor režimu
//-----------------------------------------------------------------------------
void recalcFractal(void)
{
    int bitmap[3][PIXMAP_HEIGHT][PIXMAP_WIDTH];
    int i, x, y, z;
    int min[3], max[3];                     // pro změnu kontrastu bitmapy
    float fmin[3], fmax[3];                 // pro přepočet intenzit barvových složek pixelů
    int x1, y1, x2, y2;                     // souřadnice generovaných bodů

    for (z=0; z<3; z++) {                   // pro všechny bitové roviny
        min[z]=INT_MAX;                     // nastavení pomocných proměnných
        max[z]=0;
        fmin[3]=1e10;
        fmax[3]=-1e10;
        for (y=0; y<PIXMAP_HEIGHT; y++)     // vymazání pracovní bitmapy
            for (x=0; x<PIXMAP_WIDTH; x++)
                bitmap[z][y][x]=0;
    }

    for (z=0; z<3; z++) {                   // zpracovat všechny barvové složky
        for (i=0; i<maxiter; i++) {         // iterační smyčka
            x1=rand()%PIXMAP_WIDTH;
            y1=0;
            x2=rand()%PIXMAP_WIDTH;
            y2=PIXMAP_HEIGHT-1;
            addHalfPlane(bitmap[z], x1, y1, x2, y2);// úsečka z horního k dolnímu okraji
            x1=0;
            y1=rand()%PIXMAP_HEIGHT;
            x2=PIXMAP_WIDTH-1;
            y2=rand()%PIXMAP_HEIGHT;
            addHalfPlane(bitmap[z], x1, y1, x2, y2);// úsečka z levého k pravému okraji
            if (!(i%100)) printf("%i\t", i);
        }
        // oprava intenzity rohového bodu
        bitmap[z][PIXMAP_HEIGHT-1][PIXMAP_WIDTH-1]=bitmap[z][PIXMAP_HEIGHT-2][PIXMAP_WIDTH-2];
        // získání statistiky o obrázku
        for (y=0; y<PIXMAP_HEIGHT; y++)
            for (x=0; x<PIXMAP_WIDTH; x++) {
                if (max[z]<bitmap[z][y][x]) max[z]=bitmap[z][y][x];
                if (min[z]>bitmap[z][y][x]) min[z]=bitmap[z][y][x];
            }
        printf("%c  min=%d\nmax=%d\n", "RGB"[z], min[z], max[z]);
    }

    // změna kontrastu a kopie bitmapy
    for (y=0; y<PIXMAP_HEIGHT; y++)
        for (x=0; x<PIXMAP_WIDTH; x++) {
            float f[3];
            for (z=0; z<3; z++) {           // zpracovat všechny barvové složky
                f[z]=bitmap[z][y][x];
                f[z]-=min[z];
                f[z]*=255.0/(max[z]-min[z]);
                if (fmin[z]>f[z]) fmin[z]=f[z];
                if (fmax[z]<f[z]) fmax[z]=f[z];
            }
            putpixel(pix, x, y, (int)f[0], (int)f[1], (int)f[2]);
        }
} 

Zdrojový kód třetího demonstračního příkladu je, podobně jako oba příklady předchozí, dostupný jak ve formě zdrojového textu, tak i jako HTML stránka s obarvenou syntaxí. Po překladu a spuštění je možné generovat různé tvary plasmy pomocí klávesy [Space]. Také je možné pomocí kláves [0][9] měnit maximální počet iterací, tj. počet rozdělení obrázku na poloviny.

CS24_early

fractals47_c

Obrázek 12: Další obrázek vzniklý po spuštění třetího demonstračního příkladu

7. Obsah dalšího pokračování tohoto seriálu

V následující části tohoto seriálu si ukážeme animaci plasmy (ta je mimochodem použita v mnoha demech). Také si popíšeme poslední způsob vytváření plasmy a fraktálních povrchů (terénů) – bude se jednat o metodu spektrální syntézy. Na závěr bude předveden postup vytváření trojrozměrných modelů krajiny z vytvořených obrázků plasmy.

ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

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.