Hlavní navigace

Alias a antialiasing v POV-Rayi

3. 2. 2009
Doba čtení: 19 minut

Sdílet

V dnešní části seriálu o POV-Rayi bude vysvětlena další metoda používaná pro odstranění aliasu. Jedná se o takzvaný jittering (roztřesení) aplikovaný společně se supersamplingem. Také si ukážeme, jak je možné - poněkud překvapivě - alias dokonce využít k tvorbě některých zajímavých procedurálních textur.

Obsah

1. Alias a antialiasing v POV-Rayi
2. První demonstrační příklad – využití adaptivního supersamplingu
3. Jittering (roztřesení)
4. Druhý demonstrační příklad – studie vlivu jitteringu na vizuální vzhled výsledného obrázku
5. Využití aliasu
6. Třetí demonstrační příklad – procedurální textura, ve které se využívá viditelného efektu aliasu
7. Čtvrtý demonstrační příklad – další využití aliasu při tvorbě procedurální textury zadané funkcí

1. Alias a antialiasing v POV-Rayi

V předchozí části tohoto seriálu jsme si mj. řekli, z jakého důvodu vzniká ve vykreslovaných snímcích alias a jak ho lze ve větší či menší míře eliminovat pomocí supersamplingu. Ten je založen na vyslání více primárních paprsků jedním pixelem (každý pixel je tedy považován za množinu menších subpixelů) a následným zprůměrováním barev vypočtených pro každý primární paprsek. Tímto způsobem se uměle zvyšuje „virtuální“ rozlišení obrázku a alias se tak posunuje směrem k vyšším frekvencím. POV-Ray v současnosti podporuje dvě metody supersamplingu – adaptivní nerekurzivní supersampling zapínaný volbou +AM1 a adaptivní rekurzivní supersampling, který lze povolit pomocí +AM2.

povray4601

Obrázek 1: První demonstrační příklad vykreslený bez použití antialiasingu. Všechny snímky použité v tomto článku mají rozlišení 450×450 pixelů, protože větší obrázky jsou redakčním systémem zmenšeny (resamplovány) a vliv aliasu by přestal být patrný (ostatně vykreslení snímku o větším rozlišení s jeho následným resamplingem je jedna z metod odstranění aliasu, i když má některé nedostatky, především značnou výpočetní náročnost oproti metodám adaptivním).

Při použití adaptivního nerekurzivního supersamplingu se nejprve – v prvním kroku – každým pixelem pošle pouze jeden primární paprsek a následně se provede porovnání barev dvou sousedních pixelů. V případě, že je rozdíl barev menší než zadaná mez, je pixel přímo vykreslen. Jestliže se však barvy příliš odlišují, je již použit supersampling, tj. pixelem se pošle větší množství primárních paprsků a následně se spočte jejich průměrná barva. Rozdíl barev je vypočten na základě vzorce diff = abs(r1-r2) + abs(g1-g2) + abs(b1-b2), kde rx, gx a bx jsou barevné složky obou sousedních pixelů. Mez je nastavena volbou +An.n, kterou se současně antialiasing povoluje. V případě, že je nastavena jen volba +A, je za mez dosazena výchozí hodnota 0,3.

povray4602

Obrázek 2: Snímek získaný z prvního demonstračního příkladu se zapnutým antialiasingem (a vypnutým jitteringem). Pro supersampling byla nastavena prahová hodnota 0,3. Při použití této prahové hodnoty ještě dochází ke vzniku viditelného aliasu, především v místech s velkým kontrastem (viz též následující obrázek).

Adaptivní rekurzivní supersampling vznikl dalším vylepšením supersamplingu nerekurzivního. Zatímco u výše popsané metody supersamplingu došlo na základě barevné odlišnosti dvou sousedních pixelů k vyslání buď jednoho nebo naopak maximálního nastaveného množství primárních paprsků jedním pixelem (například jeden vs. devět či šestnáct paprsků), je rekurzivní supersampling rozšířen takovým způsobem, že dochází k postupnému dělení pixelů na subpixely, přičemž pro každý subpixel je rozhodnuto, zda je již jeho dělení u konce nebo zda má dojít k jeho dalšímu rekurzivnímu rozdělení. Maximální množství primárních paprsků, které mohou být poslány jedním pixelem, se u této metody zvyšuje (s rostoucí hloubkou rekurze) velmi rychle, ve skutečnosti se však většina primárních paprsků nepoužije díky tomu, že některé subpixely nejsou dále děleny. Z praktického hlediska může být tato metoda dokonce rychlejší než její nerekurzivní varianta. Hloubku rekurze je možné ovlivnit parametrem +Rn.

povray4603

Obrázek 3: Zvýraznění některých oblastí z obrázku číslo 2, ve kterých je viditelný alias.

2. První demonstrační příklad – využití adaptivního supersamplingu

V dnešním prvním demonstračním příkladu je ukázáno použití adaptivního supersamplingu při odstraňování aliasu z procedurální textury tvořené fraktálním vzorkem, konkrétně výřezem Mandelbrotovy množiny. Fraktály vykreslované v rovině mají jednu zajímavou vlastnost – místa, v nichž dochází ke změně barvy, je možné libovolně zvětšovat bez ztráty detailu (viz také /serialy/fraktaly-v-pocitacove-grafice/). To znamená, že v ploše jednoho pixelu se potenciálně může nacházet nekonečné množství různých barev, které by byly viditelné až při větší míře zvětšení. Bez použití antialiasingu algoritmus vykreslování pošle pixelem pouze jeden primární paprsek, takže se z tohoto množství barev vybere jen barva jediná. Tento způsob vykreslování vede ke vzniku vizuálních chyb, projevujících se především na okrajích mezi vnitřní a vnější částí Mandelbrotovy množiny nebo jiného použitého fraktálu. Po zapnutí supersamplingu je jedním pixelem vysláno větší množství primárních paprsků, což výsledný vizuální dojem zlepší, alias však už z teoretického hlediska v tomto případě není možné zcela odstranit, podobně jako u dále ukázaného obrázku šachovnice v místech, kde se plocha střetává s horizontem.

povray4604

Obrázek 4: Snímek získaný z prvního demonstračního příkladu se zapnutým antialiasingem (a vypnutým jitteringem). Pro supersampling byla nastavena prahová hodnota 0,1. Alias již prakticky není viditelný.

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

// ------------------------------------------------------------
// Ukázka použití procedurální textury "mandel". Při vykreslení
// prakticky všech typů fraktálních textur dochází k aliasu,
// který není možné zcela odstranit, pouze do značné míry potlačit.
//
// rendering lze spustit příkazem:
//     povray +W450 +H300 +B100 +FN +D -A -J +Imandel.pov
//     povray +W450 +H300 +B100 +FN +D +A -J +Imandel.pov
//     povray +W450 +H300 +B100 +FN +D +A0.1 -J +Imandel.pov
//     povray +W450 +H300 +B100 +FN +D +A0.1 +R5 -J +Imandel.pov
//     povray +W450 +H300 +B100 +FN +D +AM2 -J +Imandel.pov
//     povray +W450 +H300 +B100 +FN +D +AM2 +R5 -J +Imandel.pov
//
// !POZOR: scénu je nutné vykreslit se stejným horizontálním
//         i vertikálním rozlišením!
// ------------------------------------------------------------

#version 3.0
global_settings
{
    assumed_gamma 2.2
}

#include "colors.inc"
#include "fractals.inc"        // soubor s definicí procedurálních textur

camera
{                              // nastavení kamery
    orthographic               // bez perspektivy
    location < 0, 0, -1>       // pozice kamery
    right 15*x                 // šířka a výška snímané části scény
    up 15*y
    direction z                // směr pohledu kamery (k počátku)
}

light_source
{                              // světelný zdroj
    <200, 200, -500>           // pozice
    color White                // barva
}

#declare COL1=-4.5;            // posuny objektů ve vztahu
#declare COL2= 0.0;            // k pomyslné mřížce
#declare COL3= 4.5;            // o rozměrech 3x3
#declare ROW1= 4.5;
#declare ROW2= 0.0;
#declare ROW3=-4.5;
#declare Z=0.0;

#declare OBJECT=box
{                              // testovací objekt - jednoduchý kvádr
    <-2,-2, 0>,
    < 2, 2, 1>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_01
        }
    }
    translate <COL1, ROW1, Z>
}


object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_02
        }
    }
    translate <COL2, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_03
        }
    }
    translate <COL3, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_04
        }
    }
    translate <COL1, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_05
        }
    }
    translate <COL2, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_06
        }
    }
    translate <COL3, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_07
        }
    }
    translate <COL1, ROW3, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_08
        }
    }
    translate <COL2, ROW3, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            mandel_09
        }
    }
    translate <COL3, ROW3, Z>
}
// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray4605

Obrázek 5: Při nastavení prahové hodnoty supersamplingu na 0,1 a hloubky rekurze na hodnotu 5 již alias z obrázku vymizel do té míry, že další zvyšování kvality renderingu má za následek pouze zpomalení výpočtu a na vizuální kvalitě výsledku se již nijak výrazně neprojeví.

Následuje výpis souboru fractals.inc obsahujícího definice procedurálních textur použitých v prvním demonstračním příkladu:

// ------------------------------------------------------------
// Fraktální procedurální textury získané pomocí programu
// Fractint to POV-Ray
//
// Zdrojová data vytvořená ve FractIntu: Pavel Tišnovský
// ------------------------------------------------------------
#declare mandel_01 =
    pigment { mandel 1000 frequency 3.92549019607843 phase 0
    color_map {
        [ 0 color rgbf < 0.4126984, 0.1746032, 0.3174603, 0 > ]
        [ 0.04705882 color rgbf < 0.3809524, 0.1111111, 0.2698413, 0 > ]
        [ 0.05098039 color rgbf < 0.3015873, 0.0952381, 0.2380952, 0 > ]
        [ 0.05490196 color rgbf < 0.3650794, 0.0952381, 0.2539683, 0 > ]
        [ 0.05882353 color rgbf < 0.2222222, 0.1111111, 0.2063492, 0 > ]
        [ 0.0627451 color rgbf < 0.3015873, 0.0952381, 0.2380952, 0 > ]
        [ 0.07450981 color rgbf < 0.1111111, 0.1269841, 0.1587302, 0 > ]
        [ 0.07843138 color rgbf < 0.1428571, 0.1111111, 0.1746032, 0 > ]
        [ 0.08235294 color rgbf < 0.03174603, 0.1428571, 0.1269841, 0 > ]
        [ 0.08627451 color rgbf < 0.07936508, 0.1269841, 0.1428571, 0 > ]
        [ 0.09803922 color rgbf < 0, 0, 0, 0 > ]
        [ 0.5529412 color rgbf < 0.8412699, 0.8730159, 0.9206349, 0 > ]
        [ 0.5568628 color rgbf < 0.952381, 0.952381, 1, 0 > ]
        [ 0.654902 color rgbf < 0.7460318, 0.8253968, 0.8571429, 0 > ]
        [ 0.6588235 color rgbf < 0.7936508, 0.8412699, 0.8888889, 0 > ]
        [ 0.6627451 color rgbf < 0.7142857, 0.8095238, 0.8571429, 0 > ]
        [ 0.6666667 color rgbf < 0.7777778, 0.8412699, 0.8730159, 0 > ]
        [ 1 color rgbf < 0.4126984, 0.1746032, 0.3174603, 0 > ]  }
            translate < 0.7344289075, 0.196737454, 0 >
            rotate < 0, 0, -97.5010883953612 >
            scale < 0.99993260523319, 1, 1 >
            rotate < 0, 0, 45 >
            scale < 632.992286688083, 633.002142912055, 1 >
    }

#declare mandel_02 =
    pigment { mandel 1000 frequency 3.92549019607843 phase 0
    color_map {
        [ 0 color rgbf < 1, 1, 0.5079365, 0 > ]
        [ 0.2156863 color rgbf < 0.7936508, 0.5555556, 0, 0 > ]
        [ 0.7686275 color rgbf < 0.2222222, 0, 0, 0 > ]
        [ 0.9960784 color rgbf < 0, 0, 0, 0 > ]
        [ 1 color rgbf < 1, 1, 0.5079365, 0 > ]  }
            translate < 0.2183997769606, -0.6857989345303, 0 >
            scale < 478316.318905076, 478316.326528373, 1 >
    }

#declare mandel_03 =
    pigment { mandel 1000 frequency 3.92549019607843 phase 0
    color_map {
        [ 0 color rgbf < 0.952381, 0.952381, 1, 0 > ]
        [ 0.4431373 color rgbf < 0.1587302, 0.4285714, 0.4444444, 0 > ]
        [ 0.4705882 color rgbf < 0.1587302, 0.4285714, 0.4444444, 0 > ]
        [ 0.4901961 color rgbf < 0.1111111, 0.3492064, 0.3650794, 0 > ]
        [ 0.5019608 color rgbf < 0.1111111, 0.3492064, 0.3650794, 0 > ]
        [ 0.5058824 color rgbf < 0.07936508, 0.2539683, 0.2698413, 0 > ]
        [ 0.509804 color rgbf < 0.0952381, 0.3015873, 0.3174603, 0 > ]
        [ 0.5137255 color rgbf < 0.06349207, 0.2063492, 0.2063492, 0 > ]
        [ 0.5176471 color rgbf < 0.07936508, 0.2539683, 0.2698413, 0 > ]
        [ 0.5215687 color rgbf < 0.04761905, 0.1587302, 0.1587302, 0 > ]
        [ 0.5254902 color rgbf < 0.06349207, 0.2063492, 0.2063492, 0 > ]
        [ 0.5294118 color rgbf < 0.03174603, 0.1111111, 0.1111111, 0 > ]
        [ 0.5607843 color rgbf < 0.6031746, 0.1587302, 0.4126984, 0 > ]
        [ 0.6 color rgbf < 0.6825397, 1, 1, 0 > ]
        [ 0.6235294 color rgbf < 0, 0.5555556, 0.3968254, 0 > ]
        [ 0.6862745 color rgbf < 0, 0, 0, 0 > ]
        [ 0.9921569 color rgbf < 0, 0, 0, 0 > ]
        [ 0.9960784 color rgbf < 0.8412699, 0.8730159, 0.9206349, 0 > ]
        [ 1 color rgbf < 0.952381, 0.952381, 1, 0 > ]  }
            translate < 0.218400911792272, -0.685799246545503, 0 >
            scale < 134216956004.44, 134216789339.898, 1 >
    }

#declare mandel_04 =
    pigment { mandel 300 frequency 1.18039215686275 phase 0
    color_map {
        [ 0 color rgbf < 0.6031746, 0.5555556, 0.6349207, 0 > ]
        [ 0.2156863 color rgbf < 0.3809524, 0.1111111, 0.2698413, 0 > ]
        [ 0.2196078 color rgbf < 0.3015873, 0.0952381, 0.2380952, 0 > ]
        [ 0.2235294 color rgbf < 0.3650794, 0.0952381, 0.2539683, 0 > ]
        [ 0.227451 color rgbf < 0.2222222, 0.1111111, 0.2063492, 0 > ]
        [ 0.2313726 color rgbf < 0.3015873, 0.0952381, 0.2380952, 0 > ]
        [ 0.2352941 color rgbf < 0.1904762, 0.1111111, 0.1904762, 0 > ]
        [ 0.2392157 color rgbf < 0.2222222, 0.1111111, 0.2063492, 0 > ]
        [ 0.2431373 color rgbf < 0.1111111, 0.1269841, 0.1587302, 0 > ]
        [ 0.2470588 color rgbf < 0.1428571, 0.1111111, 0.1746032, 0 > ]
        [ 0.2509804 color rgbf < 0.03174603, 0.1428571, 0.1269841, 0 > ]
        [ 0.254902 color rgbf < 0.07936508, 0.1269841, 0.1428571, 0 > ]
        [ 0.2666667 color rgbf < 0, 0, 0, 0 > ]
        [ 0.7215686 color rgbf < 0.8412699, 0.8730159, 0.9206349, 0 > ]
        [ 0.7254902 color rgbf < 0.952381, 0.952381, 1, 0 > ]
        [ 0.8235294 color rgbf < 0.7460318, 0.8253968, 0.8571429, 0 > ]
        [ 0.827451 color rgbf < 0.7936508, 0.8412699, 0.8888889, 0 > ]
        [ 0.8313726 color rgbf < 0.7142857, 0.8095238, 0.8571429, 0 > ]
        [ 0.8352941 color rgbf < 0.7777778, 0.8412699, 0.8730159, 0 > ]
        [ 1 color rgbf < 0.6031746, 0.5555556, 0.6349207, 0 > ]  }
            translate < 0.7686519325, 0.106771447, 0 >
            scale < 3997.57746805408, 3998.7843695517, 1 >
    }

#declare mandel_05 =
    pigment { mandel 500 frequency 1.96470588235294 phase 0
    color_map {
        [ 0 color rgbf < 0, 0, 0, 0 > ]
        [ 0.454902 color rgbf < 0.8412699, 0.8730159, 0.9206349, 0 > ]
        [ 0.4588235 color rgbf < 0.952381, 0.952381, 1, 0 > ]
        [ 0.5568628 color rgbf < 0.7460318, 0.8253968, 0.8571429, 0 > ]


        [ 0.5607843 color rgbf < 0.7936508, 0.8412699, 0.8888889, 0 > ]
        [ 0.5647059 color rgbf < 0.7142857, 0.8095238, 0.8571429, 0 > ]
        [ 0.5686275 color rgbf < 0.7777778, 0.8412699, 0.8730159, 0 > ]
        [ 0.6117647 color rgbf < 0.6984127, 0.7619048, 0.7936508, 0 > ]
        [ 0.9490196 color rgbf < 0.3809524, 0.1111111, 0.2698413, 0 > ]
        [ 0.9529412 color rgbf < 0.3015873, 0.0952381, 0.2380952, 0 > ]
        [ 0.9568627 color rgbf < 0.3650794, 0.0952381, 0.2539683, 0 > ]
        [ 0.9607843 color rgbf < 0.2222222, 0.1111111, 0.2063492, 0 > ]
        [ 0.9647059 color rgbf < 0.3015873, 0.0952381, 0.2380952, 0 > ]
        [ 0.9686275 color rgbf < 0.1904762, 0.1111111, 0.1904762, 0 > ]
        [ 0.972549 color rgbf < 0.2222222, 0.1111111, 0.2063492, 0 > ]
        [ 0.9764706 color rgbf < 0.1111111, 0.1269841, 0.1587302, 0 > ]
        [ 0.9803922 color rgbf < 0.1428571, 0.1111111, 0.1746032, 0 > ]
        [ 0.9843137 color rgbf < 0.03174603, 0.1428571, 0.1269841, 0 > ]
        [ 0.9882353 color rgbf < 0.07936508, 0.1269841, 0.1428571, 0 > ]
        [ 1 color rgbf < 0, 0, 0, 0 > ]  }
            translate < 0.153356958, -0.6522995075, 0 >
            scale < 9899.91189078436, 9894.26330613872, 1 >
    }

#declare mandel_06 =
    pigment { mandel 300 frequency 1.18039215686275 phase 0
    color_map {
        [ 0 color rgbf < 1, 0, 0.2857143, 0 > ]
        [ 0.05098039 color rgbf < 1, 0, 0, 0 > ]
        [ 0.2980392 color rgbf < 0, 0, 0, 0 > ]
        [ 0.3019608 color rgbf < 0, 0, 0, 0 > ]
        [ 0.4235294 color rgbf < 0.7936508, 0, 0, 0 > ]
        [ 0.5490196 color rgbf < 1, 0, 0.7936508, 0 > ]
        [ 0.6745098 color rgbf < 1, 1, 1, 0 > ]
        [ 0.8588235 color rgbf < 1, 0.03174603, 1, 0 > ]
        [ 0.8627451 color rgbf < 1, 0, 1, 0 > ]
        [ 1 color rgbf < 1, 0, 0.2857143, 0 > ]  }
            translate < 0.169440868, -0.6566112515, 0 >
            scale < 6064.79628349273, 6067.10214977623, 1 >
    }

#declare mandel_07 =
    pigment { mandel 300 frequency 1.18039215686275 phase 0
    color_map {
        [ 0 color rgbf < 0.1746032, 0, 0, 0 > ]
        [ 0.1803922 color rgbf < 0, 0, 0, 0 > ]
        [ 0.1843137 color rgbf < 1, 1, 0.5079365, 0 > ]
        [ 0.3960784 color rgbf < 0.8095238, 0.5714286, 0.01587302, 0 > ]
        [ 0.4039216 color rgbf < 0.7777778, 0.5396826, 0, 0 > ]
        [ 1 color rgbf < 0.1746032, 0, 0, 0 > ]  }
            translate < 0.1871786155, -0.6678013745, 0 >
            scale < 3997.5774680543, 3998.77370939598, 1 >
    }

#declare mandel_08 =
    pigment { mandel 300 frequency 1.18039215686275 phase 0
    color_map {
        [ 0 color rgbf < 0.8253968, 1, 0, 0 > ]
        [ 0.1490196 color rgbf < 0.03174603, 1, 0, 0 > ]
        [ 0.1529412 color rgbf < 0, 1, 0, 0 > ]
        [ 0.4 color rgbf < 0, 0, 0, 0 > ]
        [ 0.4039216 color rgbf < 0, 0, 0, 0 > ]
        [ 0.5254902 color rgbf < 0, 0.7936508, 0, 0 > ]
        [ 0.6509804 color rgbf < 0.7936508, 1, 0, 0 > ]
        [ 0.7764706 color rgbf < 1, 1, 1, 0 > ]
        [ 0.9607843 color rgbf < 1, 1, 0.03174603, 0 > ]
        [ 0.9647059 color rgbf < 1, 1, 0, 0 > ]
        [ 1 color rgbf < 0.8253968, 1, 0, 0 > ]  }
            translate < 0.03966643105, -0.6835399935, 0 >
            scale < 7513.30888753061, 7507.92085650548, 1 >
    }

#declare mandel_09 =
    pigment { mandel 300 frequency 1.18039215686275 phase 0
    color_map {
        [ 0 color rgbf < 0, 0.1746032, 1, 0 > ]
        [ 0.03137255 color rgbf < 0, 0, 1, 0 > ]
        [ 0.2784314 color rgbf < 0, 0, 0, 0 > ]
        [ 0.282353 color rgbf < 0, 0, 0, 0 > ]
        [ 0.4039216 color rgbf < 0, 0, 0.7936508, 0 > ]
        [ 0.5294118 color rgbf < 0, 0.7936508, 1, 0 > ]
        [ 0.654902 color rgbf < 1, 1, 1, 0 > ]
        [ 0.8392157 color rgbf < 0.03174603, 1, 1, 0 > ]
        [ 0.8431373 color rgbf < 0, 1, 1, 0 > ]
        [ 1 color rgbf < 0, 0.1746032, 1, 0 > ]  }
            translate < 0.202761775, -0.673907104, 0 >
            scale < 1253.15010607916, 1253.2563778217, 1 >
    } 

3. Jittering (roztřesení)

POV-Rayi je možné antialiasing rozšířit ještě o další metodu, jež může v některých případech pomoci potlačit vizuální vliv aliasu na výsledné obrázky. Jedná se o takzvaný jittering (roztřesení) používaný společně se supersamplingem. Princip jitteringu je velmi jednoduchý – původně pravidelná mřížka určující body, ve kterých primární paprsky protínají projekční rovinu, se při aplikaci jitteringu „znáhodní“ tak, že body průniku jsou odsunuty ze své původní polohy o vektor vypočtený generátorem náhodných čísel. Přitom je však zaručeno, že bod neopustí prostor určený plochou subpixelu, pro nějž se barva počítá.

povray4606

Obrázek 6: Šachovnice vykreslená bez použití antialiasingu.

Nepatrné posunutí primárních paprsků vede k tomu, že se do původního vzorku vytvořeného vlivem aliasu vnese náhodnost, která sice alias nepotlačí (ani ho neposune směrem k vyšším frekvencím), ovšem pro lidské vnímání je alias modifikovaný jitteringem méně rušivý než původní pravidelné moaré. Zajímavé je, že i v lidském oku dochází díky uspořádání světlocitlivých a barvocitlivých buněk k velmi dokonalému jitteringu, proto je lidský zrak vůči aliasu do značné míry imunní (pokud by nebyl, nešlo by například sledovat televizi či monitor).

povray4607

Obrázek 7: Tento snímek byl vykreslen s povoleným supersamplingem, ale vypnutým jitteringem.

povray4608

Obrázek 8: Tento snímek byl vykreslen s povoleným supersamplingem i jitteringem.

4. Druhý demonstrační příklad – studie vlivu jitteringu na vizuální vzhled výsledného obrázku

Scéna představovaná druhým demonstračním příkladem je velmi jednoduchá, protože obsahuje pouze jeden viditelný objekt. Jedná se o plochu, na níž je nanesena obligátní šachovnicová textura. Vlivem perspektivy dochází k podvzorkování šachovnice (v blízkosti horizontu) a tím pádem i ke vzniku aliasu. Na obrázcích 7 až 12 je patrný vliv jednotlivých metod antialiasingu. Snímek nejvyšší kvality byl získán použitím adaptivního supersamplingu, při kterém mohlo jedním pixelem procházet až 25 primárních paprsků, jenž byl zkombinován s výše popsaným jitteringem. Samozřejmě je možné dále snižovat mez, při níž dojde k aplikaci supersamplingu či zvyšovat maximální počet primárních paprsků, ovšem to pouze povede k delšímu času výpočtu – ostatně všechny metody antialiasingu (zejména ty implementované na grafických akcelerátorech) jsou založeny na určitém kompromisu mezi výpočetní náročností a kvalitou výsledku.

// ------------------------------------------------------------
// Druhý demonstrační příklad - vliv antialiasingu na výsledný
// obrázek, ve kterém kvůli perspektivě dochází k podvzorkování
// šachovnicové textury a tím pádem i ke vzniku aliasu.
//
// rendering lze spustit příkazem:
// povray +W450 +H300 +B100 +FN +D -A +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +A +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +A0.1 +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +A0.1 +R5 +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +AM2 +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +AM2 +R5 +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +A -J +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +A0.1 -J +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +A0.1 -J +R5 +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +AM2 -J +Iantialias.pov
// povray +W450 +H300 +B100 +FN +D +AM2 -J +R5 +Iantialias.pov
// ------------------------------------------------------------

// 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)
// (kamera je nastavena tak, aby byl v horní třetině obrázku viditelný
// horizont)
camera
{
    perspective
    sky +y                               // natočení kamery ve směru osy y
    location  <40.0, 40.0, -40.0>        // pozice kamery v prostoru
    look_at   <15.0, 14.0, 15.0>         // pohled kamery - střed obrázku
}

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

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

light_source
{
    < 32, 50, 20>                        // pozice třetího světelného zdroje
    color LightGray                      // barva světla
}

// podkladová rovina
plane
{
    y, -15
    texture
    {                                    // textura - vlastnosti povrchu
        pigment
        {                                // šachovnicová textura
            checker                      // vyvedená ve stupních šedi
            color rgb <0.3, 0.3, 0.3>
            color rgb <0.5, 0.5, 0.5>
        }
        finish
        {                                // odlesky a odrazy na povrchu
            diffuse 0.7
            reflection 0.2
            ambient 0.7
        }
        scale 10
    }
}


// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray4609

Obrázek 9: Mez pro supersampling je nastavena na hodnotu 0,1, jittering je zakázaný.

povray4610

Obrázek 10: Mez pro supersampling je nastavena na hodnotu 0,1, jittering je povolený.

povray4611

Obrázek 11: Mez pro supersampling je nastavena na hodnotu 0,1, počet primárních paprsků procházejících jedním pixelem dosahuje 25, jittering je zakázaný.

povray4612

Obrázek 12: Mez pro supersampling je nastavena na hodnotu 0,1, počet primárních paprsků procházejících jedním pixelem dosahuje 25, jittering je povolený. Výsledný obrázek má prakticky nejvyšší možnou kvalitu, další zvyšování úrovně rekurze již nevede k podstatnému zlepšení vizuálního dojmu.

5. Využití aliasu

Alias, kterému se většinou v počítačové grafice (ale i v dalších oborech) snažíme vyhnout, je možné v některých případech s výhodou využít. Jednou z možností použití aliasu v POV-Rayi je generování procedurálních textur zadaných uživatelsky definovanou matematickou funkcí. Pokud má obrazec generovaný touto funkcí větší frekvenci, než je vzorkovací frekvence odpovídající rozlišení rastrového obrázku, může díky podvzorkování a interferenci podvzorkovaného obrazu s původním obrazem vzniknout zajímavá textura. Použití těchto textur s sebou nese jednu nevýhodu – v případě, že se při renderingu zapne některá z metod antialiasingu, interferenční vzorek zmizí nebo je poškozen. Stejné poškození vzorku nastane v případě zmenšení obrazu algoritmem provádějícím resampling. I přes tyto nevýhody mají textury založené na aliasu svoje oblasti použití – viz obrázek číslo 15.

povray4613

Obrázek 13: Procedurální textura specifikovaná uživatelem definovanou funkcí.

6. Třetí demonstrační příklad – procedurální textura, ve které se využívá viditelného efektu aliasu

Použití procedurální textury zadané uživatelsky definovanou funkcí, při níž vzniká (zde chtěný) alias, je ukázáno na třetím demonstračním příkladu. V něm je vytvořena funkce nazvaná jednoduše FUNCTION, která má tvar 50xx+50yy. Vlivem aliasu je ve výsledné textuře viditelný vzorek složený z velkého množství navzájem se překrývajících kružnic, jejichž tvar a velikost závisí mj. i na zvoleném zvětšení textury. Na čtrnáctém obrázku je zobrazen snímek získaný renderingem tohoto příkladu bez použití antialiasingu, přičemž každý kvádr je pokrytý texturou s jiným zvětšením. Na textuře vykreslené v pravém dolním rohu je patrné, že při dostatečně velkém zvětšení vzorek vzniklý aliasem zmizí, protože rozlišení obrázku (tj. vlastně vzorkovací frekvence) je již dostatečné – nedochází ke vzniku signálu s nižší frekvencí, než je frekvence vzorkovací.

povray4614

Obrázek 14: Snímek vzniklý renderingem třetího demonstračního příkladu v POV-Rayi bez použití antialiasingu.

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

// ------------------------------------------------------------
// Třetí demonstrační příklad.
// Ukázka použití procedurální textury zadané matematickou funkcí,
// u které se využívá efektu aliasu.
//
// rendering lze spustit příkazem:
//     povray +W1024 +H1024 +B100 +FN +D +Itextures.pov +Otextures.png
//
// !POZOR: scénu je nutné vykreslit se stejným horizontálním
//         i vertikálním rozlišením a vypnutým antialiasingem!
// ------------------------------------------------------------

#version 3.0
global_settings                // globální nastavení parametrů scény
{
    assumed_gamma 2.2
}

#include "colors.inc"

camera                         // nastavení kamery
{
    orthographic               // bez perspektivy
    location < 0, 0, -1>       // pozice kamery
    right 15*x                 // šířka a výška snímané části scény
    up 15*y
    direction z                // směr pohledu kamery (k počátku)
}

light_source                   // světelný zdroj
{
    <200, 200, -500>           // pozice
    color White                // barva
}

#declare COL1=-4.5;            // posuny objektů ve vztahu
#declare COL2= 0.0;            // k pomyslné mřížce
#declare COL3= 4.5;            // o rozměrech 3x3
#declare ROW1= 4.5;
#declare ROW2= 0.0;
#declare ROW3=-4.5;
#declare Z=0.0;

#declare COLMAP1 = color_map   // náhrada původní barvové mapy
{
    [0.02 color rgb <0.65, 0.45, 0.25> ]
    [0.06 color rgb <0.55, 0.40, 0.20> ]
    [0.10 color rgb <0.15, 0.10, 0.05> ]
    [1.00 color rgb <0.75, 0.60, 0.40> ]
}

#declare COLMAP2 = color_map   // druhá barvová mapa
{
    [0.0  color Blue]          // hodnota 0 je dolní mezí, pro kterou lze specifikovat barvu
    [0.7  color White]
    [1.0  color Red]           // hodnota 1 je naopak horní mezí
}

#declare COLMAP3 = color_map   // třetí barvová mapa
{
    [0.0  color Yellow]        // hodnota 0 je dolní mezí, pro kterou lze specifikovat barvu
    [0.7  color Black]
    [1.0  color Red]           // hodnota 1 je naopak horní mezí
}

#declare OBJECT = box
{                              // testovací objekt - jednoduchý kvádr
    <-2,-2, 0>,
    < 2, 2, 1>
}

// kvůli této funkci je nutné vypnout antialiasing
// - vzorek textury je tvořený právě aliasem
#declare FUNCTION = function
{
    50*x*x+50*y*y
}

// devět objektů potažených texturou v různém zvětšení (měřítku)
object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP1
            }
            scale 0.25
        }
    }
    translate <COL1, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP1
            }
            scale 0.50
        }
    }
    translate <COL2, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP1
            }
            scale 0.75
        }
    }
    translate <COL3, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            scale 1.0
        }
    }
    translate <COL1, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            scale 1.5
        }
    }
    translate <COL2, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            scale 2.0
        }
    }
    translate <COL3, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP3
            }
            scale 3.0
        }
    }
    translate <COL1, ROW3, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP3
            }
            scale 4.0
        }
    }
    translate <COL2, ROW3, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP3
            }
            scale 6.0
        }
    }
    translate <COL3, ROW3, Z>
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray4615

Obrázek 15: Detailní pohled na prostřední texturu.

7. Čtvrtý demonstrační příklad – další využití aliasu při tvorbě procedurální textury zadané funkcí

Také v dnešním čtvrtém a současně i posledním demonstračním příkladu je pro pokrytí devíti kvádrů použita procedurální textura zadaná vlastní funkcí. Tentokrát se jedná o funkci, která má tvar f(x,y,z)=50xxx-50yyy. Vzorek tvořený touto texturou je již zajímavější, protože kromě soustředných kružnic vzniklých aliasem můžeme v obrázku vidět i další tvary. Způsob použití textury specifikované výše uvedenou funkcí je shodný s předchozím demonstračním příkladem. Poslední tři kvádry jsou pokryty texturou posunutou ze svého středu – pro posun je použita lineární transformace textury zadaná atributem translate, šlo by však změnit i vlastní zápis funkce, například takto: f(x,y,z)=50(x-posunx)(x-posunx)(x-posunx)+50(y-posuny)(y-posuny)(y-posuny) se stejným výsledkem (použití lineární transformace je samozřejmě jednodušší i flexibilnější). Povšimněte si dvojího významu lineární transformace translate: ve vnitřním uzlu je použita pouze pro posun textury po povrchu horní stěny kvádru, v uzlu vnějším pak pro posun celého kvádru společně s texturou.

povray4616

Obrázek 16: Screenshot čtvrtého demonstračního příkladu vykresleného v POV-Rayi bez použití antialiasingu.

Cloud 24 - tip 1

Zdrojový kód čtvrtého demonstračního příkladu má tvar:

// ------------------------------------------------------------
// Čtvrtý demonstrační příklad.
// Ukázka použití procedurální textury zadané matematickou funkcí,
// u které se využívá efektu aliasu.
//
// rendering lze spustit příkazem:
//     povray +W1024 +H1024 +B100 +FN +D +Itextures.pov +Otextures.png
//
// !POZOR: scénu je nutné vykreslit se stejným horizontálním
//         i vertikálním rozlišením a vypnutým antialiasingem!
// ------------------------------------------------------------

#version 3.0
global_settings                // globální nastavení parametrů scény
{
    assumed_gamma 2.2
}

#include "colors.inc"

camera                         // nastavení kamery
{
    orthographic               // bez perspektivy
    location < 0, 0, -1>       // pozice kamery
    right 15*x                 // šířka a výška snímané části scény
    up 15*y
    direction z                // směr pohledu kamery (k počátku)
}

light_source                   // světelný zdroj
{
    <200, 200, -500>           // pozice
    color White                // barva
}

#declare COL1=-4.5;            // posuny objektů ve vztahu
#declare COL2= 0.0;            // k pomyslné mřížce
#declare COL3= 4.5;            // o rozměrech 3x3
#declare ROW1= 4.5;
#declare ROW2= 0.0;
#declare ROW3=-4.5;
#declare Z=0.0;

#declare COLMAP1 = color_map   // náhrada původní barvové mapy
{
    [0.02 color rgb <0.65, 0.45, 0.25> ]
    [0.06 color rgb <0.55, 0.40, 0.20> ]
    [0.10 color rgb <0.15, 0.10, 0.05> ]
    [1.00 color rgb <0.75, 0.60, 0.40> ]
}

#declare COLMAP2 = color_map   // druhá barvová mapa
{
    [0.0  color Blue]          // hodnota 0 je dolní mezí, pro kterou lze specifikovat barvu
    [0.7  color White]
    [1.0  color Red]           // hodnota 1 je naopak horní mezí
}

#declare OBJECT = box
{                              // testovací objekt - jednoduchý kvádr
    <-2,-2, 0>,
    < 2, 2, 1>
}

// kvůli této funkci je nutné vypnout antialiasing
// - vzorek textury je tvořený právě aliasem
#declare FUNCTION = function
{
    50*x*x*x-50*y*y*y
}

// devět objektů potažených texturou v různém zvětšení (měřítku)
object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP1
            }
            scale 0.50
        }
    }
    translate <COL1, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP1
            }
            scale 0.75
        }
    }
    translate <COL2, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP1
            }
            scale 1.00
        }
    }
    translate <COL3, ROW1, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            scale 1.2
        }
    }
    translate <COL1, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            scale 1.5
        }
    }
    translate <COL2, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            scale 2.0
        }
    }
    translate <COL3, ROW2, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            translate <-1,-1,0>
            scale 2.0
        }
    }
    translate <COL1, ROW3, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function

            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            translate <-1,1,0>
            scale 2.0
        }
    }
    translate <COL2, ROW3, Z>
}

object
{
    OBJECT
    texture
    {
        pigment
        {
            function
            {
                FUNCTION(x,y,z)
            }
            color_map
            {
                COLMAP2
            }
            translate <1,-1,0>
            scale 2.0
        }
    }
    translate <COL3, ROW3, Z>
}

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray4617

Obrázek 17: Tato textura je založena na uživatelsky definované funkci: 50xxx+50yy(y-1*x).

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.