Obsah
Výpočet barvy vrcholů pomocí evaluátorůVýpočet barvy bodů na Bézierově křivce
Vykreslení Bézierovy křivky
Výpočet barvy bodů na Bézierově ploše
Vykreslení Bézierovy plochy
Demonstrační příklady
Obsah dalšího pokračování
Seznam funkcí OpenGL zmíněných v této části
Nové funkce OpenGL popsané v této části
Zkomprimovaná verze článku s přílohami
Výpočet barvy vrcholů pomocí evaluátorů
V předchozích dílech seriálu o OpenGL evaluátorech jsme si podrobně popsali, jakým způsobem je možné evaluátory použít pro získání souřadnic vrcholů libovolných grafických primitiv, které leží buď na Bézierově křivce, nebo na Bézierově ploše obecně libovolného řádu. Zatím nám však chyběla možnost výpočtu barev jednotlivých vrcholů.
Vzhledem k tomu, že se barvy na povrchu objektu počítají pomocí bilineární interpolace (Gouraudovo stínování), je nutné specifikovat barvu pouze pro každý zadávaný vrchol na povrchu; barvy vlastního povrchu se vypočtou automaticky na grafickém akcelerátoru v průběhu rasterizace jednotlivých trojúhelníků.
Při vykreslování Bézierových křivek či ploch je možné kromě automatizovaného výpočtu souřadnic vrcholů vypočítat i barvy jednotlivých vrcholů. Postup je takový, že se specifikují polohy řídících bodů Bézierovy křivky či plochy, souřadnice těchto bodů však neleží v ploše ani v trojrozměrném prostoru, ale ve čtyřrozměrném barvovém prostoru RGBA. V tomto prostoru odpovídá každé barvě jedna souřadnice. Hodnoty souřadnic řídících bodů by měly ležet v rozsahu 0–1, tj. uvnitř „barvové kostky RGBA“.
Během výpočtu bodů, které leží na křivce či ploše v RGBA prostoru, tak nemůže nikdy dojít k tomu, že by souřadnice bodu ležely mimo rozsah 0–1, protože všechny body musí ležet v konvexní obálce vzniklé ze všech řídících bodů – to je jedna ze základních vlastností Bézierových křivek a ploch.
V dalším textu si popíšeme dvě různé možnosti použití evaluátorů pro výpočet barvy: výpočet barvy bodů, které leží na Bézierově křivce a výpočet barvy bodů, které leží na Bézierově ploše.
Výpočet barvy bodů na Bézierově křivce
Výpočet barvy bodů na Bézierově křivce pomocí evaluátorů je velmi jednoduchý. Nejdříve je zapotřebí povolit použití evaluátorů pro výpočet jak souřadnic bodů, tak i jejich barev. V programu může povolení vypadat například následovně:
// povolení evaluátorů pro vyhodnocování barev glEnable(GL_MAP1_COLOR_4); // povolení evaluátorů pro vyhodnocování souřadnic glEnable(GL_MAP1_VERTEX_3);
Dále je již možné do evaluátorů dosadit řídící body použitých Bézierových křivek. V demonstračních příkladech používám pro obě křivky pole čtyř řídících bodů, tj. obě křivky mají stejný stupeň. V případě řídících bodů Bézierovy křivky s informacemi o vrcholech má každý bod tři souřadnice:
// řídící body Bézierovy křivky // v trojrozměrném prostoru GLfloat ctrlPoints[4][3] = { {100.0, 100.0, 0.0}, {400.0, 100.0, 0.0}, {400.0, 400.0, 0.0}, {100.0, 400.0, 0.0} };
řídící body Bézierovy křivky v barvovém prostoru RGBA mají čtyři souřadnice, kde každá souřadnice odpovídá jedné barvové složce:
// řídící body Bézierovy křivky // v prostoru RGBA GLfloat colorPoints[4][4] = { {1.0, 1.0, 0.0, 1.0}, {0.0, 1.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 1.0}, {1.0, 0.0, 0.0, 1.0} };
Dosazení řídících bodů těchto Bézierových křivek do příslušných evaluátorů je možné provést pomocí příkazu glMap1f(), který byl podrobněji popsán ve čtvrté části tohoto seriálu. Pro křivku vykreslovanou v 3D prostoru má příkaz glMap1f() tvar:
// dosadit řídící body do evaluátoru glMap1f( GL_MAP1_VERTEX_3, // typ evaluátoru 0.0, // počáteční hodnota t 1.0, // koncová hodnota t 3, // vzdálenost mezi hodnotami 4, // stupeň křivky &ctrlPoints[0][0] // řídící body );
Příkaz pro přenos řídících bodů křivky v barvovém prostoru RGBA má poněkud odlišný tvar, protože se mění vzdálenost mezi dvěma stejnými souřadnicemi v poli sousedních řídících bodů (každý řídící bod má čtyři souřadnice):
// dosadit řídící křivky v RGBA body do evaluátoru glMap1f( GL_MAP1_COLOR_4, // typ evaluátoru 0.0, // počáteční hodnota t 1.0, // koncová hodnota t 4, // vzdálenost mezi hodnotami 4, // stupeň křivky &ctrlPoints[0][0] // řídící body );
Vykreslení Bézierovy křivky
Po zadání obou typů evaluátorů je možné křivku vykreslit. Smyčku pro vykreslování jsme si popsali již v předchozích dílech, ovšem zde dochází k jedné změně – nemusí se zadávat příkazy typu glColor*() pro specifikaci barvy, protože barva je vypočtena na základě polohy bodu Bézierovy křivky v prostoru RGBA:
// vykreslení Bézierovy křivky jako polyčáry, // která má 100 vrcholů glBegin(GL_LINE_STRIP); for (i=0; i<=100; i++) { glEvalCoord1f((GLfloat) i/100.0); } glEnd();
Před vykreslováním dalších prvků grafické scény nesmíme zapomenout na vypnutí obou evaluátorů, jinak by mohlo dojít k chybnému výpočtu vrcholů dalších těles. Proto se musí zavolat příkazy:
// zákaz obou typů evaluátorů glDisable(GL_MAP1_COLOR_4); glDisable(GL_MAP1_VERTEX_3);
Celý postup specifikace a vykreslení Bézierovy křivky s výpočtem barvy jednotlivých vrcholů je ukázán v prvním a druhém demonstračním příkladu.
Výpočet barvy bodů na Bézierově ploše
Výpočet barvy bodů na Bézierově ploše pomocí evaluátorů je v mnoha směrech podobný výpočtu barvy bodů na Bézierově křivce. Oba postupy se liší pouze v počtu parametrů. Zatímco u Bézierových křivek bylo nutné specifikovat pouze jeden parametr t, u Bézierových ploch jsou to dva na sobě nezávislé parametry u a v.
Proto se místo jednodimenzionálního evaluátoru používá evaluátor dvoudimenzionální. To je patrné z parametrů všech funkcí pracujících s evaluátory: místo konstanty GL_MAP1_COLOR4 se předává konstanta GL_MAP2_COLOR4.
Nejdříve si ukažme, jak se bude specifikovat pole s řídícími body pro plochu v prostoru. Každý řídící bod má tři souřadnice, a vzhledem k tomu, že se bude vykreslovat Bézierova bikubická křivka, je zapotřebí specifikovat 4×4=16 bodů:
// řídící body Bézierovy bikubické // plochy v trojrozměrném prostoru GLfloat ctrlPoints[4][4][3] = { { {-1.5,-1.5, 4.0}, {-0.5,-1.5, 2.0}, { 0.5,-1.5,-1.0}, { 1.5,-1.5, 2.0} }, { {-1.5,-0.5, 1.0}, {-0.5,-0.5, 3.0}, { 0.5,-0.5, 0.0}, { 1.5,-0.5,-1.0} }, { {-1.5, 0.5, 4.0}, {-0.5, 0.5, 0.0}, { 0.5, 0.5, 3.0}, { 1.5, 0.5, 4.0} }, { {-1.5, 1.5,-2.0}, {-0.5, 1.5,-2.0}, { 0.5, 1.5, 0.0}, { 1.5, 1.5,-1.0} } };
Pro demonstraci faktu, že stupeň obou ploch může být odlišný, bude v barvovém prostoru RGBA použita Bézierova plocha prvního stupně, což znamená, že se ve skutečnosti bude při výpočtu barvy provádět jednoduchá bilineární interpolace mezi hodnotami barvy specifikovanými ve čtyřech bodech (je samozřejmě možné použít i křivky vyšších stupňů):
// řídící body Bézierovy křivky // v barvovém prostoru RGBA GLfloat colorPoints[2][2][4] = { { { 1.0, 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0, 0.0} }, { { 1.0, 0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0, 0.0} } };
Předání řídících bodů Bézierovy plochy se spolu s body plochy v barvovém RGBA prostoru provádí pomocí příkazu glMap2f(), který byl podrobněji popsán v páté části tohoto seriálu:
// předání řídících bodů // Bézierovy bikubické plochy glMap2f( GL_MAP2_VERTEX_3, // typ evaluátoru 0, // rozsah hodnot 1, // parametru u 3, // vzdálenost hodnot 4, // stupeň B. polynomu 0, // rozsah hodnot 1, // parametru v 12, // vzdálenost hodnot 4, // stupeň B. polynomu &points[0][0][0] ); // předání řídících bodů // pro výpočet barev pomocí evaluatorů glMap2f( GL_MAP2_COLOR_4, // typ evaluátoru 0, // rozsah hodnot 1, // parametu u 4, // vzdálenost hodnot 2, // stupeň B. polynomu 0, // rozsah hodnot 1, // parametru v 8, // vzdálenost hodnot 2, // stupeň B. polynomu &colorPoints[0][0][0] );
Vykreslení Bézierovy plochy
V následujícím úseku kódu bude ukázáno, jakým způsobem se může Bézierova plocha vykreslit, spolu s povolením a následným zákazem činnosti evaluátorů:
int i,j; // povolení obou typů 2D evaluátorů glEnable(GL_MAP2_VERTEX_3); glEnable(GL_MAP2_COLOR_4); // začátek vykreslování bodů glBegin(GL_POINTS); // osa _u_ v parametrickém prostoru for (i=0; i<=30; i++) { // osa _v_ v parametrickém prostoru for (j=0; j<=30; j++) { // výpočet polohy a barvy bodu glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/30.0); } } glEnd(); // zákaz aplikace obou typů evaluátorů glDisable(GL_MAP2_VERTEX_3); glDisable(GL_MAP2_COLOR_4);
Celý postup specifikace řídících bodů a následného vykreslení Bézierovy křivky s dopočtem barvy jednotlivých vrcholů je ukázán ve třetím demonstračním příkladu.
Demonstrační příklady
Po spuštění prvního demonstračního příkladu se vykreslí Bézierova křivka, která je vypočtena pomocí OpenGL evaluátorů. Výpočet bodů, jež leží na Bézierově křivce, probíhá ve funkci drawBezierUsingEvaluators(). Barvy jednotlivých bodů na křivce (resp. vrcholy vykreslované polyčáry) jsou taktéž vypočteny pomocí jednorozměrného evaluátoru, který na základě hodnoty jednoho parametru t vypočte souřadnici bodu ve čtyřrozměrném barvovém prostoru RGBA.
Stiskem klávesy ESC nebo Q lze aplikaci ukončit, klávesa F přepne zobrazení na celou obrazovku, klávesa W přepne zobrazení zpět do okna o přednastavené velikosti 450×450 pixelů.
Zdrojový kód prvního demonstračního příkladu je dostupnýzde, HTML verze se zvýrazněním syntaxe zde.
Obrázek 1: Screenshot prvního demonstračního příkladu
Druhý demonstrační příklad je podobný příkladu prvnímu. Jediný rozdíl spočívá v tom, že u druhého příkladu je možné měnit polohu jednotlivých řídících bodů Bézierovy křivky pomocí myši se stisknutým levým tlačítkem. V horní části okna aplikace jsou zobrazeny pozice jednotlivých řídících bodů a číslo právě vybraného řídícího bodu.
Další ovládání aplikace pomocí klávesnice je stejné jako u prvního demonstračního příkladu, podobně jako výpočet barvy jednotlivých bodů na Bézierově křivce s využitím evaluátorů.
Zdrojový kód druhého demonstračního příkladu je dostupný zde, HTML verze se zvýrazněním syntaxe zde.
Obrázek 2: Screenshot druhého demonstračního příkladu
Po spuštění třetího demonstračního příkladu se vykreslí Bézierova bikubická plocha (plát), která je vypočtena s využitím 2D evaluátorů. Výpočet probíhá ve funkci drawBezierSurfaceUsingEvaluators(). Bézierova plocha se zobrazí pomocí jednotlivých bodů vykreslovaných grafickou primitivou GL_POINT. Barva každého bodu je vypočtena na základě dalšího evaluátoru, který vyčísluje souřadnici bodu ve čtyřrozměrném prostoru RGBA.
Pohled na Bézierovu plochu je animovaný, animaci lze spustit a opět zastavit pomocí klávesy S. Klávesou ESC je možné program ukončit, klávesou F se provede přepnutí okna na celou obrazovku. Opětovné zmenšení okna na velikost 450×450 pixelů se provede stisknutím klávesy W.
Zdrojový kód třetího demonstračního příkladu je dostupný zde, HTML verze se zvýrazněním syntaxezde.
Obrázek 3: Screenshot třetího demonstračního příkladu
Obsah dalšího pokračování
V dalším pokračování tohoto seriálu si ukážeme, jakým způsobem lze evaluátory použít při specifikaci texturovacích souřadnic – budeme vykreslovat Bézierovy plochy, jež jsou korektně pokryté texturou.
Seznam funkcí OpenGL zmíněných v této části
glBegin()glColor*()
glDisable()
glEnable()
glEnd()
Nové funkce OpenGL popsané v této části
Následující funkce sice již byly popsány v předchozích částech, ale zde mají nový význam:
glMap1f()glMap2f()
glEvalCoord1f()
glEvalCoord2f()
Zkomprimovaná verze článku s přílohami
Zkomprimovaná verze tohoto článku je umístěna zde.