KMI 24. listopadu 2014
Voxelová grafika Zobecnění rasterové grafiky do 3D (zobecnění pojmu pixel na pojem voxel). Konkurence k povrchové (polygonové reprezentaci). Výhody: skutečná hloubka (schopnost zachytit vnitřek objektu), zajímavé vlastnosti (rekurzivní materiály, fraktály), destruktibilní. Nevýhody: špatná manipulace s objekty (bone animace).
Využití praktická motivace CT, NMR skeny, studium materiálů ve strojírenství. 3D tisk. Hry. Lze použít pro Global Illumination next gen grafika blížící se kvalitou raytracingu vykreslovaná v reálném čase.
Reprezentace obrazu Voxelová grafika Spojitý 2D obraz Obrázek velikosti (doména) w h, w, h R je zobrazení dvojic do barevného prostoru (rozsahu). Zobrazení, kde se každé pozici v obrázku přiřazuje barva. I : [1, w] [1, h] [0, 1], kde [1, w] R, [1, h] R, [0, 1] R
Diskrétní 2D obraz Ve skutečnosti, ani svět není spojitý fyzika zná diskrétní částice i nejmenší velikost tzv. Planckova délka. I d : [1, w] [1, h] [0, c max ] [1, w] N, [1, h] N, [0, c max ] N Pixel picture element Necht I d je diskrétní obraz. Pixel p je prvek diskrétního 2D obrazu, čili p I d. Je to tedy nějaká dvojice tvaru x, y, c.
Diskrétní 3D obraz Diskrétní 2D obraz můžeme intuitivně zobecnit do libovolného prostoru (tedy i do 3D) I : [1, w] [1, h] [1, d] [0, c max ] [1, w] N, [1, h] N, [1, d] N, [0, c max ] N Voxel volumetric element Voxel je to samé co pixel, pouze má jinou doménu.
Problémy Pamět ová složitost O(N 3 ), kde N = max({w, h, d}). Jak to vykreslovat a jde to v reálném čase vůbec? Bone animace - prakticky nemožné. Rasterové animace - není probém (až na velikost).
Dokážeme zredukovat pamět ovou složitost? Tvrzení: Diskrétní 3D I velikosti w h d obraz má pamět ovou složitost O(N 3 ), kde N = max({w, h, d}). Obraz I je zobrazení, tedy podmnožina kartézského součinu. V těchto zobrazeních nelze obecně najít žádnou závislost, protože můžeme za obraz považovat také náhodné obrazy. Z teorie informace víme, že takové obrazy nelze efektivně komprimovat. Poznámka: Není to ale až tak pesimistické, jak to vypadá, některé obrazy závislost vykazují například přirozené obrázky.
Reprezentace voxelové grafiky 3D maticí, stejně jako ve 2D. Run-length. SVO (Sparse Voxel Octree) oktalový strom. N 3 tree. Adaptive octree vlastní invence. kd-stromy, spatial hashing.
Maticová reprezentace raw kódování Prakticky stejné jako.bmp. Jednorozměrné pole délky w h d Bpp bitů, Bpp znamená počet bitů na pixel. Adresace voxelu <x,y,z> přístupem do pole V pomocí V[w*h*z*Bpp + w*y*bpp + x*bpp] Časová složitost je tedy O(1). Spotřeba paměti je přesně whd Bpp O(N 3 ), Ω(N 3 ). Na 32-bitových strojích nelze pracovat s maticovými modely většími než 1024 3, což je málo. Ideální pro reprezentaci náhodných a malých modelů.
Run-length kódování Voxelová grafika Analogické k run-length ve 2D. Základem je 2D obraz (1024 1024), který má ukazatele na run-length kódované sloupce. V praxi implementováno.vxl formátem, může mít zápornou komprimaci. Použité v dosových hrách na Build enginu od Kena Silvermana (Blood, Shadow Warrior, Duke Nukem 3D). Engine VOXLAP, Command & Conquer série.
SVO Sparse Voxel Octree Metoda dělení prostoru pomocí stromu. Každý uzel octree představuje krychli, má 8 potomků (pokud není listový), potomci rovnoměrně dělí prostor rodiče na 8 podkrychlí. Lze optimalizovat tak, že sjednotíme potomky právě když mají stejnou barvu nebo jsou prázdné velká úspora paměti v řídkých modelech. Adresační metoda kd-shortstack a její varianty (kd-backtrack, kd-restart). Pamět je ale stále O(N 3 ), octree však může vykazovat zápornou komprimaci.
SVO Sparse Voxel Octree Proč má octree složitost stále O(N 3 )? Označíme úrovně octree l {0, 1, 2,...}, plný octree pak má v každé úrovni n l = 8 l nodů, celkový počet uzlů octree výšky h = log 2 N je pak tedy. S = h l=0 8 l = 1 8log 2 N+1 1 8 = 8N3 1 7 O(N 3 ) Adresace listového uzlu má časovou složitost O(log 2 N), což bývá malé číslo pro běžné modely.
Sestavení oktalového stromu optimal_p <- function( node ){ if( each( node->childs, function( child ){ return child == NULL; } ) ) return EMPTY; if( each( node->childs, function( child ){ return (child->leaf_p && (child->color == node->childs[0]->color)); })) { return SAME; } } return FALSE;
optimize <- function( node ){ for( i = 0 ; i < 8 ; i++ ){ optimize( node->childs[i] ); } switch( optimal_p( node ) ){ case SAME: node->color = node->childs[0]->color; memset( node->childs, NULL ); return node; break; case EMPTY: return NULL; break; default: return node; } }
N 3 strom Zobecnění octree, potomků může být N 3 pro libovolné N N, octree je speciální případ, kdy N = 2. Hluboké listové oblasti se nahrazují raw modelem velikosti M 3 opatřené mipmapou rychlejší procházení. Pamět je ale stále O(N 3 ), podobný argument jako u octree. Adresace listového uzlu má časovou složitost O(logN). Hodnoty M a N se volí při kompilaci (převodu na N 3 strom). Efektivita kódování závisí na volbě konstant M a N na začátku.
Adaptive octree Vlastní (zatím nepublikovaná) invence. Kompromis mezi raw modely a octree modely (přebírá pouze dobré vlastnosti obou). Reprezenentace vhodná pro ukládání na disk, neumí mipmapping. Velký potenciál i pro rychlý rendering. Zabraňuje záporné komprimaci. Adresace listového uzlu má časovou složitost O(log 2 N). Ve skutečnosti je adresace v praxi ale vždy lepší než u octree o nějaký faktor (v případě reálného renderingu to není zanedbatelné).
Adaptive octree detaily Uzly mohou být podobně jako v případě N 3 stromu raw modely, ale bez mipmapy. V opačném případě jsou uzly běžné octree uzly. K degenraci octree podstromu na raw model dojde v případě, že jeho celková velikost překročí velikost raw modelu, pak už totiž není octree výhodný z hlediska paměti (a ani času jak uvidíme později). V extrémním případě (plný model s nezkomprimovatelnými voxely) zdegeneruje na raw model. Zamezení záporné komprimaci a značná úspora paměti v běžných řídkých modelech. Adresace je oproti octree výhodnější alespoň o nějaký pevně daný faktor závislý na implmentaci. Ve skutečnosti znamená adaptive octree úsporu více než 50% zabrané paměti oproti octree
Adaptive octree detaily pokračování optimize <- function( node ){ for( i = 0 ; i < 8 ; i++ ){ optimize( node->childs[i] ); } switch( optimal_p( node ) ){ case SAME: node->color = node->childs[0]->color; memset( node->childs, NULL ); return node; break; case EMPTY: return NULL; break;
Adaptive octree detaily pokračování 2 } default: break; } if( octree_memory_sz( node ) > node.bbox.wˆ3*sizeof(argb32_color) ) return octree_to_raw( node ); return node;
Adaptive octree vlastnosti Věta: Vztah pamět ové složitosti mezi octree a adaptive octree Pamět zabraná modelem reprezentovaným pomocí adaptive octree je menší nebo rovna témuž modelu, který je reprezentován octree. Věta: Vztah pamět ové složitosti mezi raw kódováním a adaptive octree Mějme obraz velikosti 2 k 2 k 2 k pro nějaké k N, množství zabrané paměti modelem kódovaným pomocí adaptive octree je menší roven tomu samému modelu kódovanému pomocí raw metody.
Důsledek: O kódování voxelového obrazu Mějme obraz I. AOCTREE(I) OCTREE(I), RAW (I) Zobrazení AOCTREE, OCTREE, RAW přiřazují obrazu počet zabraných bajtů v paměti při daném kódování.
Adaptive octree reálná data Název testu Rozměry obrazu Raw formát Octree formát Adaptive octree simple 1024 1024 1024 3GB 4KB 4KB voxlap 1024 1024 256 1GB 44MB 22MB myhead 512 512 512 512MB 71MB 23MB myhead2 512 512 512 512GB 64MB 20MB Tabulka : Tabulka srování velikosti souborů podle modelů. Název testu Octree/raw Adaptive octree/raw simple 0,000000020 0,000000020 voxlap 0,042965651 0,021837585 myhead 0,138260350 0,044120207 myhead2 0,123718247 0,039568335 Tabulka : Tabulka kompresního poměru octree variant vůči raw modelu.
Metody vykreslování voxelové grafiky Rasterizace reprezentace voxelů pomocí krychlí 12 polygonů na krychli. Rasterizace se používá v populární hře Minecraft (vhodná pro extrémně přiblížené modely). Raycasting poprvé interaktivní ve hře Wolfenstein 3D (1991), vržení paprsku přes vykreslovací surface. Raytracing zobecněný raycasting, počítá se světly, extrémně náročné. Conetracing vhodné zobecnění raytracingu pro octree a jeho varianty. Voxelové modely lze vykreslovat v reálném čase (GigaVoxels GPGPU, VoXen i686).
Raytracing na SVO Voxelová grafika Algoritmus vykreslení přímky podobné jako DDA, Bresenhamův algoritmus. Algoritmus musí počítat s tím, že voxely mohou být nestejně velké Potřeba rychlého algoritmu ořezávání přímky krychlí vlastní invence. Adresace stojí O(log 2 N), v nejhorším případě stojí vykreslení přímky O(N) kroků, tudíž celková složitost je O(Nlog 2 N).
Raycasting, Raytracing Raycasting Metoda, která obrací fyzikální princip šíření světla do oka/senzoru a trasuje pozpátku fotony, které mohou dopadnout na sítnici. Tím filtruje zbytečné fotony, kterých je většina. Pro každý obrazový pixel je potřeba vypočítat jeho barvu. Jakmile zpětně šířený foton dopadne na povrch materiálu, přiřadí se tato barva příslušnému pixelu. Raytracing To samé jako Raycasting, ale při dopadu se pokračuje dále ke světlům lze tak docílit efektu nasvětlování a stínování.
Optimalizační aspekty procházení nehomogenní mřížky Výpočet průsečíků krychle s přímkou je nejkritičtější výpočet při raytracingu voxelových dat. První trik spočívá v zarovnání modelu na osy souřadnicového systému, tím pádem není nutné nic transformovat (kromě paprsků, ale těch je málo, navíc postačí jedna transformační matice. Když máme zarovnání, problém se redukuje pouze na 2 násobení (dělení si můžeme předpočítat dopředu) a test, zda bod leží na stěně krychle. Navíc můžeme setřídit stěny podle pravděpodobnosti, která bude nejspíše zasažena podle převládající složky vektoru.
Procházení oktalového stromu podél přímky Stačí umět spočítat průsečík paprsku s výstupní rovinou krychle Potom stačí umět adresovat voxel v oktalovém stromě (kd-restart) Nabízí se optimalizace, protože k sousedním voxelům (listům) oktalového stromu často vede podobná cesta, většinou je výhodnější si cestu pamatovat a používat ji (neplatí vždy) Tato metoda se jmenuje kd-backtrack, je výhodná zejména v případě grafických karet, kde je extrémně drahý přístup do sdílené paměti
Adresace voxelu kd-restart kd_restart <- function( node, cube = <x,y,z,w>, inpoint ){ if( node->leaf_p ){ return <node, cube>; } midpoint <- < cube.x + cube.w/2, cube.y + cube.w/2, cube.z + cube.w/2 >; path <- < inpoint.x >= midpoint.x, inpoint.y >= midpoint.y, inpoint.z >= midpoint.z >; return kd_restart( GetChild( path.x, path.y, path.z ), < cube.x + path.x*(w/2), cube.y + path.y*(w/2), cube.x + path.z*(w/2) >, inpoint ); }
Procházení homogenní (ekvidistantní) mřížky function line(x0, x1, y0, y1) int deltax := x1 - x0 int deltay := y1 - y0 real error := 0 real deltaerr := abs (deltay / deltax) int y := y0 for x from x0 to x1 plot(x,y) error := error + deltaerr if error >= 0.5 then y := y + 1 error := error - 1.0
Knihovna VoXen Knihovna pro raytracing nad voxelovými modely (dosud implementované modely raw a octree). Modely lze doplnit doprogramování příslušného interface (Adaptive octree dosud nemá raytracing). Softwarová implementace (i386, AMD64), výhledově GPGPU pomocí OpenCL (infrastruktura je definována). Psáno v jazyce C99, implementovány 2 ovladače SDL a NULL Drv, Unix. Podpora dynamického nasvětlování pomocí bodového osvětlení a ambientní osvětlení.
Knihovna VoXen vlastnosti Jednoduchá na pochopení, snadné napsat jednoduchý program (cca 10 řádků). Jednoduchý prohlížeč voxelových modelů implementovatelný v cca 150 řádcích. Rychlost zhruba 5-40FPS (softwarově a bez světel). Počítá s multiplatformností a svobodnou licencí. Výhledová implementace pomocí GPGPU výpočtů skrze OpenCL, streamingu, radiozity a měkkých stínů, lightmapy.
Knihovna VoXen obrazové výstupy
Jak se dostat k obrazovým datům Hry Kena Silvermana Blood, Shadow Warrior, VOXLAP, Voxelstein, Command&Conquer. Pár modelů jsem našel na http://graphics.stanford.edu/data/voldata/. Zapojit se do výzkumného programu a nechat si naskenovat vlastní tělo můj případ.
Otázky?
Zdroje Mark Agate, Richard L. Grimsdale, Paul F. Lister The HERO Algorithm for Ray-Tracing Octrees, LSI & Graphics Research Group School of Engineering, University of Sussex Brighton BNl 9QT, UK, 1989. John Amanatides, Andrew Woo A Fast Voxel Traversal Algorithm for Ray Tracing, Dept. of Computer Science University of Toronto Toronto, Ontario, Canada M5S 1A4, 2011. Cyril Crassin, Fabrice Neyret, Sylvain Lefebvre, Elmar Eisemann GigaVoxels: Ray-Guided Streaming for Efficient and Detailed Voxel Rendering, LJK / INRIA / Grenoble Universities / CNRS, INRIA Sophia-Antipolis, MPI Informatik / Saarland University, 2009.
R. S. Ferguson Practical Algorithms for 3D Computer Graphics, A K Peters, Ltd., 2001. ISBN: 1-56881-154-3 T. Foley, J. Sugerman KD-Tree Acceleration Structures for a GPU Raytracer, HWWS: Proceedings of the ACM SIGGRAPH/EUROGRAPHICS, 2005. Hall, J.R. Programming Linux Games. No Starch Press, San Francisco, 2001. Herout Pavel. Učebnice jazyka C. Kopp, České Budějovice, 1999. Timothy L. Kay, James T. Kajiya Ray Tracing Complex Scenes, California Institute of Technology Pasadena, CA 91125.
K. Römisch Sparse Voxel Octree Ray Tracing on the GPU, Master s Thesis, Department of Computer Science, Aarhus University, Denmark, 2009. Sedgewick Robert. Algorithms in C. Addison-Wesley, Princenton University, 2007. J. Žára, B. Beneš, J. Sochor, P. Felkel Moderní počítačová grafika, 2. vydání, Computer Press, 2005. ISBN: 80-251-0454-0 Simple DirectMedia Layerhttp://www.libsdl.org/ [online] 2013, http://www.libsdl.org/ [cit. 2013-2-19]. Ken Silverman s Voxlap Pagehttp://advsys.net/ken/voxlap.htm [online] 2013, http://advsys.net/ken/voxlap.htm [cit. 2013-4-10].