Hlavní navigace

OpenGL evaluátory (7)

22. 6. 2004
Doba čtení: 7 minut

Sdílet

V dnešním pokračování seriálu o OpenGL evaluátorech si popíšeme, jakým způsobem lze evaluátory použít při výpočtu barev bodů, jež leží na Bézierových křivkách či plochách. Toto použití evaluátorů sice nepatří mezi typické (na rozdíl od vyhodnocování souřadnic jednotlivých vrcholů), ale může v některých případech urychlit a zjednodušit vykreslování modelů těles.

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 jednodimenzio­ná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 drawBezierUsin­gEvaluators(). 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.

Screenshot prvního demonstračního příkladu
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.

Screenshot druhého demonstračního příkladu
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 drawBezierSur­faceUsingEvalu­ators(). 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.

Screenshot třetího demonstračního příkladu
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.

UX DAy - tip 2

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.

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.