15. října 2013, Brno Připravil: David Procházka Projekce Počítačová grafika 2
Projekce Strana 2 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Projekce Strana 3 / 38 Způsob vykreslování scény 1 Prohlížení nastavení kamery do scény (nastavujeme směr, kterým se kamera bude dívat ) pohledová transformace. 2 Modelování vkládáme objekty do scény modelovací transformace. 3 Projekce nastavujeme tvar záběru (měníme nastavení objektivu: ohnisková vzdálenost, atp.) projekční transformace. 4 Zobrazení zvětšení/zmenšení a namapování výsledného obrázku objektů ve scéně do požadované roviny zobrazovací transformace. (Analogie s fotoaparátem)
Projekce Strana 4 / 38 Princip nastavení projekce
Projekce Strana 5 / 38 Obecný princip implementace zobrazení Pohledová a modelovací matice (modelview matrix) se bude dynamicky měnit za běhu programu. Nastavení je obvykle nutné vložit do funkce řešící vykreslování objektů. Projekce způsob zobrazení scény zůstavá po celou dobu běhu aplikace obvykle stejná. Až na: 1 Potřebujeme změnit způsob zobrazení scény (CAD). 2 Změnil se tvar okna, do kterého provádíme vykreslování. Varianta 1 nás nezajímá, podstatná je varianta 2. Zavedeme novou funci void glutreshapefunc(void (*func)(int width, int height)). Tato funkce reaguje na změnu velikosti okna, do kterého se provádí vykreslování. Zaregistrovaná funkce obdrží v parametrech width a height aktuální velikost okna.
Projekce Strana 6 / 38 Nastavení projekce Abychom mohli projekci nastavit, je nutné aktivovat nastavení projekční matice. K tomuto nám slouží příkaz glmatrixmode (GL PROJECTION). Od tohoto okamžiku jsou všechny maticové příkazy automaticky aplikovány na projekční matici. První operace, kterou s projekční maticí provedeme její nastavení na jednotkovou matici pomocí příkazu glloadidentity(). Tento krok je doporučený z toho důvodu, že řada dalších operací modifikuje aktuálně používanou matici.
Ortografická projekce Strana 7 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Ortografická projekce Strana 8 / 38 Ortografická projekce Ortografická projekce představuje pravoúhlý hranol. Objekty se vzdáleností nemění svoji velikost. Používáme v aplikacích jako je CAD, kde jsou klíčové skutečné rozměry objektů. Pro nastavení používáme při práci v trojrozměrném prostoru příkaz void glortho(gldouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far). Parametry near/far představují vzdálenosti k bližší/vzdálenější rovině, ne absolutní pozice v souřadném systému!
Ortografická projekce Strana 9 / 38 Nastavení ortografické projekce
Ortografická projekce Strana 10 / 38 Ortografické projekce boční pohled
Ortografická projekce Strana 11 / 38 Ortografická projekce implementace Celý kód by se mohl nacházet v onresize() 1 // nastaveni oblasti pro zobrazeni 2 glviewport(0, 0, 640, 480); 3 // nebo glviewport (0, 0, width, height); 4 5 // zaciname nastavovani projekcni matice 6 glmatrixmode(gl_projection); 7 8 // nastavime ji na jednotkovou 9 glloadidentity(); 10 11 // opet je lepsi pouzit promenne reprezentujici 12 // velikost okna 13 glortho(-5.0,5.0,-5.0,5.0,0.0,5.0);
Ortografická projekce Strana 12 / 38 2D ortografická projekce Speciální případem je 2D ortografická projekce. V tomto případě je použit příkaz void gluortho2d(gldouble left, GLdouble right, GLdouble bottom, GLdouble top). Parametry definují levý dolní a pravý dolní roh okna. Je možné použít i příkaz glortho() s tím, že nastavíme souřadnice pro osu z na hodnoty -1.0 a 1.0 (z u objektů bude rovno 0).
Ortografická projekce Strana 13 / 38 2D orto. projekce implementace Celý kód by se mohl nacházet v onresize() 1 // nastaveni oblasti pro zobrazeni 2 glviewport(0, 0, 640, 480); 3 // nebo glviewport (0, 0, width, height); 4 5 // zaciname nastavovani projekcni matice 6 glmatrixmode(gl_projection); 7 8 // nastavime ji na jednotkovou 9 glloadidentity(); 10 11 // opet je lepsi pouzit promenne reprezentujici 12 // velikost okna 13 gluortho2d(0, 640, 0, 480);
Perspektivní projekce Strana 14 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Perspektivní projekce Strana 15 / 38 Perspektivní projekce Scéna je definována jako komolý jehlan. Pokud je objekt o určitých rozměrech nachází v blízké ořezové rovině, zabírá větší část plochy, než pokud by byl ve vzdálené. Proto se blízký objekt jeví větší. Pro nastavení lze využít je void glfrustum(gldouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far). Bývá často nahrazen příkazem void gluperspective(gldouble fovy, GLdouble aspect, GLdouble near, GLdouble far). gluperspective vytváří vždy pouze symetrický komolý jehlan.
Perspektivní projekce Strana 16 / 38 Nastavení perspektivní projekce
Perspektivní projekce Strana 17 / 38 Perspektivní projekce boční pohled
Perspektivní projekce Strana 18 / 38 Perspektivní projekce implementace Celý kód by se mohl nacházet v onresize() 1 // nastaveni oblasti pro zobrazeni 2 glviewport(0, 0, 640, 480); 3 // nebo glviewport (0, 0, width, height); 4 5 // zaciname nastavovani projekcni matice 6 glmatrixmode(gl_projection); 7 8 // nastavime ji na jednotkovou 9 glloadidentity(); 10 11 // nastaveni projekce 12 glfrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
Nastavení pohledové matice Strana 19 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Nastavení pohledové matice Strana 20 / 38 Nastavení pohledové matice Je k dopozici příkaz glulookat(gldouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz). Jeho parametry reprezentují tři základní věci: pozici kamery GLdouble eyex, GLdouble eyey, GLdouble eyez, bod do kterého je kamera natočena GLdouble centerx, GLdouble centery, GLdouble, centerz, směr vzhůru (tedy natočení kamery) GLdouble upx, GLdouble upy, GLdouble upz.
Nastavení pohledové matice Strana 21 / 38 Obvyklé nastavení Vysunutí kamery podél osy z ven ze scény. Směr vzhůru bude podél osy y. (Pozoroval si pomyslně couvne, aby viděl celou scénu). Toto nastavení bude reprezentováno kódem 1 glulookat( 2 0.0, 0.0, -5.0, 3 0.0, 0.0, 0.0, 4 0.0, 1.0, 0.0)
Nastavení pohledové matice Strana 22 / 38 Příklady nastavení pohledové matice Běžné couvnutí a komplikové natočení
Nastavení pohledové matice Strana 23 / 38 Popis nastavení předchozího obrázku 1 Příklad vlevo: Kamera je vysunuta ze scény podél osy z na pozici [0.0, 0.0, -4.0], zaměřena na střed scény [0.0, 0.0, 0.0], směr nahoru je definován jako rovnoběžný s osou y. 2 Příklad vpravo: Kamera ležící na souřadnicích [3.0, 0.0, -4.0], zaměřena lehce nad střed scény [0.0, 2.0, 0.0], nakloněna doprava pod úhlem 45 stupňů [1.0, 1.0, 0.0]. Dávejte pozor na orientaci os. Kladná poloosa osy z směřuje dovnitř obrazovky.
Detaily implementace Strana 24 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Detaily implementace Strana 25 / 38 Přesné nastavené orto. projekce Mějme trojúhelníky s následujícími souřadnicemi a barvami: 1 GLint triangle[] = { 2 0, 5, 5, 3-5, -5, 5, 4 5, -5, 5, 5 1, 5, 2, 6-4, -5, 2, 7 6, -5, 2}; 8 9 GLfloat colors[] = { 10 1.0, 0.0, 0.0, 11 0.0, 1.0, 0.0, 12 0.0, 0.0, 1.0, 13 1.0, 1.0, 0.0, 14 1.0, 1.0, 0.0, 15 1.0, 0.0, 1.0};
Detaily implementace Strana 26 / 38 Nastavení orto. projekce
Detaily implementace Strana 27 / 38 Nastavení orto. projekce 1 Souřadice v intervalu < 5, 5 > na osách x a y. Osa z je zobrazována ve vzdálenosti 0 až 5 od pozorovatele. Pozorovatel umístěn do souřadnic [0,0,0] a otočen ve směru kladné poloosy osy z. Směr vzhůru je definován ve směru osy y. glortho(-5.0,5.0,-5.0,5.0,0.0,5.0); glulookat(0.0,0.0,0.0,0.0,0.0,1.0,0.0,1.0,0.0); 2 Zadní trojúhelník vypuštěn: glortho(-5.0,5.0,-5.0,5.0,0.0,4.0); glulookat(0.0,0.0,0.0,0.0,0.0,1.0,0.0,1.0,0.0); 3 Směr pohledu je vektor. Bod pohledu udává bod na linii pohledu. glortho(-5.0,5.0,-5.0,5.0,0.0,5.0); glulookat(0.0,0.0,0.0,0.0,0.0,10.0,0.0,1.0,0.0);
Detaily implementace Strana 28 / 38 Nastavení orto. projekce 2
Detaily implementace Strana 29 / 38 Nastavení orto. projekce 2 1 Pozorovatel ustoupil vzad po ose z na pozici [0,0,-1], proto se zobrazovaný kvádr v prostoru posunul a zadní trojúhelník zmizel. glortho(-5.0,5.0,-5.0,5.0,0.0,5.0); glulookat(0.0, 0.0,-1.0,0.0,0.0,10.0,0.0,1.0,0.0) 2 Velikost (rozsah) os x a y byla zvětšena na dvojnásobek větší okolí. glortho(-10.0,10.0,-10.0,10.0,0.0,5.0); glulookat(0.0,0.0,0.0,0.0,0.0,10.0,0.0,1.0,0.0); 3 Směr vzhůru byl definován ve směru os x a y. Objekt je otočen o 45 stupňů. Objekt deformovaný (okno nerovnoměrné) glortho(-10.0,10.0,-10.0,10.0,0.0,5.0); glulookat(0.0,0.0,0.0,0.0,0.0,10.0,1.0,1.0,0.0);
Detaily implementace Strana 30 / 38 Nastavení perspektivní projekce 1 Pokud ponecháme v nastavení projekce stejné parametry. Pouze změňme příkaz glortho() za glfrustrum(). Dostaneme zcela odlišný výsledek (část 1 následujícího obrázku). 2 glfrustum(-5.0, 5.0, -5.0, 5.0, 1.0, 6.0); glulookat(0.0,0.0,10.0,0.0,0.0,0.0,0.0,1.0,0.0); 3 Vzdálené objekty se tedy jeví menší. Bližší (žluto-růžový) se zmenšil, vzdálenější zcela zmizel. Byl překryt bližším objektem. 4 Pozor na to, které pametry v příkazech znamenají pozice a které vzdálenosti!
Detaily implementace Strana 31 / 38 Výsledek nastavení Vlevo: skrytý zadní trojúhelník. Vpravo: po posunu pozorovatele vidíme zadní trojúhelník.
Testování hloubky Strana 32 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Testování hloubky Strana 33 / 38 Testování hloubky Mějme trojúhelníky: 1 GLint triangle[] = { 2 1, 5, 2, 3-4, -5, 2, 4 6, -5, 2, 5 0, 5, 5, 6-5, -5, 5, 7 5, -5, 5}; 8 9 GLfloat colors[] = { 10 1.0, 1.0, 0.0, 11 1.0, 1.0, 0.0, 12 1.0, 0.0, 1.0, 13 1.0, 0.0, 0.0, 14 0.0, 1.0, 0.0, 15 0.0, 0.0, 1.0};
Testování hloubky Strana 34 / 38 Výsledek Pro jsou opačně? Rozhodovalo pořadí vykreslení!
Testování hloubky Strana 35 / 38 Testování hloubky Pro ukládání informací o vzdálenosti objektů se používá pamět hloubky (Depth Buffer/Z-buffer). Je nutné provést následující: 1 Do bitových příznaků předávaných funkce glutinitdisplaymode() přidáme GLUT DEPTH. 2 Povolíme použití paměti hloubky pomocí příkazu glenable(gl DEPTH TEST). 3 glcleardepth(glfloat depth), hodnota mazání paměti hloubky mezi snímky (0.0 až 1.0). 4 Nastavení typu testu hloubky. Obvykle se nastavuje funkce GL LESS (bližší objekt překreslí objekt vzdálenější). 5 Mazání paměti hloubky před vykreslením každého snímku. To lze provést bud samostatně zavoláním funkce glclear(gl DEPTH BUFFER BIT). Lze smazat zároveň bufferem barev. Současné mazání bufferů je rychlejší.
Shrnutí Strana 36 / 38 Obsah přednášky 1 Projekce 2 Ortografická projekce 3 Perspektivní projekce 4 Nastavení pohledové matice 5 Detaily implementace 6 Testování hloubky 7 Shrnutí
Shrnutí Strana 37 / 38 Shrnutí A nezapomínat na testování hloubky!
Shrnutí Strana 38 / 38 Kontrolní otázky/úkoly Vytvořte aplikaci, která vykreslí dva trojúhelníky v prostoru. Pomocí klávesnice zapínejte a vypínejte testování hloubky a přepínejte projekce (a její nastavení).