OpenGL evaluátory (8)

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

Sdílet

Dnešní díl seriálu o OpenGL evaluátorech je věnován výpočtům texturovacích souřadnic pomocí evaluátorů. Při vykreslování Bézierových křivek a ploch je možné na jejich povrch nanášet textury, protože se tyto objekty při vykreslování rozdělí na geometrická primitiva OpenGL. Souřadnice textur nemusí být zadávány ručně či programovým výpočtem, lze použít automatizovaný výpočet souřadnic s pomocí evaluátorů.

Obsah

Základní informace o texturování a návaznost na evaluátory
Generování texturovacích souřadnic pomocí 1D evaluátorů
Generování texturovacích souřadnic pomocí 2D evaluátorů
Ukázka použití evaluátorů
Demonstrační příklady
Obsah dalšího pokračování
Seznam funkcí OpenGL zmíněných v této části
Zkomprimovaná verze článku i s přílohami

Základní informace o texturování a návaznost na evaluátory

V seriálu o grafické knihovně OpenGL, zejména v dílech XXII, XXIII,XXIV, XXV, XXVI, XXVII, XXVIII, XXIX a XXX jsem se podrobně zabýval způsobem pokrytí ploch vykreslovaných objektů rastrovým obrázkem – texturou. Ve stručnosti je možné říci, že pro úspěšné vykreslení otexturované plochy je zapotřebí provést čtyři operace:

  1. Vytvořit texturovací objekt a nastavit tento objekt jako aktivní.
  2. Vhodně nastavit všechny vlastnosti texturovacího objektu.
  3. Nahrát do texturovacího objektu texturu, tj. vlastní rastrový obrázek.
  4. Při vykreslování tělesa specifikovat pro každý vrchol souřadnici do textury.

Pokud bude pomocí příkazů OpenGL vykreslováno těleso, jehož povrch je složený z jednotlivých plošek (ať již trojúhelníků, čtyřúhelníků, či plošných polygonů), nebývá se zadáním souřadnic do textury problém, protože každý vrchol je specifikován příkazem glVertex*(), u nějž je možné doplnit barvu, normálový vektor a také texturovací souřadnici. Při použití texturování (bez výpočtu osvětlení) pak vypadá posloupnost příkazů pro specifikaci jednotlivých vrcholů následovně (předpokládám použití plošné rastrové textury, což je v počítačové grafice zdaleka nejběžnější případ):

// vykreslení povrchu tělesa s texturou
glBegin(typ_grafické_primitivy);
    glTexCoord2f(u, v);   // souřadnice do textury
    glVertex3f(x, y, z);  // souřadnice vrcholu
    // zde následují další vrcholy
glEnd();

Problém však může nastat v případě, že se má vykreslit Bézierova plocha, která je specifikována pouze pomocí řídících bodů, které obecně neleží na povrchu Bézierovy plochy – viz první obrázek.

Objekt složený z několika Bézierových plátů
Obrázek 1: Objekt složený z několika Bézierových plátů

Typický fragment kódu pro vykreslení Bézierovy plochy bez specifikace texturovacích souřadnic vypadá takto:

//-----------------------------------------------
// Tato funkce vykreslí Bézierovu plochu z bodů
//-----------------------------------------------
void drawBezierSurfaceUsingEvaluators(
    GLfloat points[][4][3])
{
  int i,j;

  // předání řídících bodů Bézierovy plochy
  glMap2f(GL_MAP2_VERTEX_3, // počítat polohy vertexů
          0,                // rozsah mapování
          1,                //  parametru u
          3,                // počet hodnot mezi par. u
          4,                // dimenze ve směru u
          0,                // rozsah mapování
          1,                //  parametru v
          12,               // počet hodnot mezi par. v
          4,                // dimenze ve směru v
          &points[0][0][0]);

  // 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 bodu a přenos
      // do vykreslovacího řetězce
      glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/30.0);
    }
  }
  glEnd();
}

Z předchozího kódu je patrné, že při „ručním“ výpočtu texturovacích souřadnic by bylo nutné před každým zavoláním funkce glEvalCoord2f() zavolat i funkci pro specifikaci souřadnic [u, v] v prostoru textury. Tím by se však ztratila největší výhoda evaluátorů, tj. minimalizace dat, která proudí po sběrnici z operační paměti počítače do grafického akcelerátoru.

Horší případ nastane, pokud se Bézierova křivka či plocha vykresluje pomocí dvojice funkcí glMapGrid2*() a glEvalMesh2(), protože v tomto případě nemáme přístup ke smyčce, ve které se jednotlivé řídící body vyčíslují, a tím pádem pro ně také nelze zapsat souřadnice do textury.

Proto je v OpenGL umožněno dopočítávat i souřadnice do textury pomocí evaluátorů. V dalším textu budu předpokládat, že se používají plošné rastrové textury, tj. klasické pixmapy (obrázky), ovšem evaluátory lze použít i pro jednorozměrné a trojrozměrné (objemové) textury.

Generování texturovacích souřadnic pomocí 1D evaluátorů

Nejprve se podívejme na možnosti, které nám evaluátory pro práci s texturami poskytují, posléze si ukážeme i konkrétní příklad jejich použití. Pro práci s texturovacími souřadnicemi lze použít jak jednodimenzionální, tak i dvojdimenzionální evaluátor. Dimenzí evaluátoru je zde myšlen počet parametrů, které je nutno zadat do rovnice parametrické křivky či plochy. U jednodimenzi­onálního evaluátoru se jedná o parametr t, u dvojdimenzi­onálního evaluátoru se používají dva na sobě nezávislé parametryu a v.

Evaluátor však může pro své zadané parametry vracet více hodnot, typicky to jsou souřadnice v ploše či v prostoru. Současně musí mít řídící body zadané křivky či plochy stejnou dimenzi (tj. stejný počet souřadnic) jako body počítané evaluátorem.

Bližší informace o jednodimenzi­onálních evaluátorech jsem podal ve čtvrté části tohoto seriálu, informace o dvojdimenzi­onálních evaluátorech jsou popsány v části páté.

Jednodimenzionální evaluátor, který je specifikován řídícími body Bézierovy křivky, může být nastaven tak, že jako svou hodnotu nevrací souřadnice vrcholu v prostoru, ale souřadnice do textury. To, kolik souřadnic bude vráceno a jaký mají význam, je specifikováno prvním parametrem ve funkci glMap1f(), který může pro potřeby generování texturovacích souřadnic nabývat hodnot:

  • GL_MAP1_TEXTU­RE_COORD1 – řídící body Bézierovy křivky jsou zadány pouze jednou souřadnicí. Při použití evaluátoru jsou v grafickém vykreslovacím řetězci vypočteny souřadnice do jednorozměrné textury. Účinek je podobný jako při použití příkazu glTexCoord1().
  • GL_MAP1_TEXTU­RE_COORD2 – řídící body Bézierovy křivky jsou zadány dvěma souřadnicemi v rovině textury. Výsledkem použití takto vytvořeného evaluátoru je dvojice souřadnic [s, t], které udávají pozici v plošné textuře. Účinek je podobný použití příkazuglTexCo­ord2(). Tento typ evaluátoru je pro naše účely nejvhodnější, protože souřadnice v rastrové textuře se udává právě dvojicí hodnot.
  • GL_MAP1_TEXTU­RE_COORD3 – řídící body Bézierovy křivky jsou zadány třemi souřadnicemi, takže se při použití evaluátoru generují tři souřadnice [s, t, r], podobně jako při použití příkazu glTexCoord3(). Použití tohoto typu evaluátoru je možné u objemových (voxelových) textur.
  • GL_MAP1_TEXTU­RE_COORD4 – řídící body Bézierovy křivky jsou zadány čtyřmi souřadnicemi, takže se generují čtyři souřadnice do textury [s, t, r, q], podobně jako při použití funkce glTexCoord4(). Čtvrtá souřadnice je použita při nelineárním mapování textur – to bylo popsáno v seriálu o OpenGL.

Generování texturovacích souřadnic pomocí 2D evaluátorů

Dvojdimenzionální evaluátor, který je specifikován řídícími body Bézierovy plochy, může být nastaven tak, aby jako svou hodnotu vracel souřadnice do textury. Podobně jako u 1D evaluátoru, i zde lze nastavit, kolik souřadnic má být počítáno a jaký mají význam. Nastavení se provádí přes první parametr funkce glMap2f():

  • GL_MAP2_TEXTU­RE_COORD1 – řídící body Bézierovy plochy jsou zadány jednou souřadnicí. Při práci s evaluátorem se generují stejná data jako v případě použití příkazu glTexCoord1().
  • GL_MAP2_TEXTU­RE_COORD2 – řídící body Bézierovy plochy jsou zadány dvojicí souřadnic. Použití je stejné jako v případě příkazu glTexCoord2() – generují se souřadnice pro rastrovou plošnou texturu.
  • GL_MAP2_TEXTU­RE_COORD3 – řídící body Bézierovy plochy jsou zadány třemi souřadnicemi. S tímto typem evaluátoru se pracuje v případě, že se používají objemové (voxelové) textury.
  • GL_MAP2_TEXTU­RE_COORD4 – řídící body Bézierovy plochy jsou zadány čtyřmi souřadnicemi, čehož lze využít při nelineárním mapování textur.

V počítačové grafice se nejčastěji používají plošné rastrové textury, proto se pracuje s evaluátorem, jehož vstupem i výstupem jsou dvě souřadnice – provádí se tedy mapování z jednoho 2D prostoru do jiného 2D prostoru.

Výpočet texturovacích souřadnic se provádí tak, že se nastaví jak evaluátory pro výpočet souřadnic vrcholů, tak i evaluátory pro výpočet souřadnic do textury. Ukázka kódu, který provádí vykreslení otexturované Bézierovy plochy, je uvedena v dalším odstavci.

Ukázka použití evaluátorů

V následující funkci je ukázáno, jakým způsobem je možné evaluátory použít pro vykreslení otexturované Bézierovy plochy. Tato funkce je součástí níže uvedených demonstračních příkladů.

//-----------------------------------------------
// Tato funkce vykreslí otexturovanou Bézierovu
// plochu pomocí evaluátorů.
//-----------------------------------------------
void drawBezierSurfaceUsingEvaluators()
{
#define DELENI 20
  int i,j;

  // povolení 2D evaluátoru
  glEnable(GL_MAP2_VERTEX_3);

  // povolení evaluátoru pro výpočet text. souřadnic
  glEnable(GL_MAP2_TEXTURE_COORD_2);

  // předání řídících bodů Bézierovy plochy
  glMap2f(
    GL_MAP2_VERTEX_3,
    0, 1, 3, 4,
    0, 1,12, 4,
    &points[0][0][0]);
  // předání řídících bodů pro výpočet
  // texturovacích souřadnic pomocí evaluátorů
  glMap2f(
    GL_MAP2_TEXTURE_COORD_2,
    0, 1, 2, 2,
    0, 1, 4, 2,
    &texturePoints[0][0][0]);

  // vykreslení Bézierovy plochy
  glMapGrid2f(DELENI, 0.0f, 1.0f, DELENI, 0.0f, 1.0f);
  glEvalMesh2(GL_FILL, 0, DELENI, 0, DELENI);

  // zákaz aplikace obou typů evaluátorů
  glDisable(GL_MAP2_VERTEX_3);
  glDisable(GL_MAP2_TEXTURE_COORD_2);
}

Demonstrační příklad

Po spuštění prvního demonstračního příkladu se vykreslí Bézierova bikubická plocha, která je vypočtena pomocí evaluátorů. Výpočet probíhá ve funkci drawBezierSur­faceUsingEvalu­ators(). Bézierova plocha se zobrazí pomocí plošek vykreslovaných primitivou GL_QUADS. Každá ploška je otexturovaná, přičemž textura je počítána lineární interpolací pomocí evaluátorů.

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

Po spuštění druhého demonstračního příkladu se taktéž vykreslí Bézierova bikubická plocha. V čase jsou měněny pozice některých řídících bodů, čímž dochází k zajímavým efektům. Tento demonstrační příklad pouze ukazuje vliv změny řídících bodů na Bézierovu plochu, reálně toho využijeme ve třetím příkladu.

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 3: Screenshot druhého demonstračního příkladu

Ve třetím demonstračním příkladu se vykreslí Bézierova bilineární plocha, která je otexturována, přičemž se textura počítá na základě Bézierovy bikubické plochy. Změna souřadnic do textury je průběžně měněna, čímž se dosahuje zajímavých efektů.

Zdrojový kód druhého demonstračního příkladu je dostupný zde, HTML verze se zvýrazněním syntaxe zde.

Screenshot třetího demonstračního příkladu
Obrázek 3: Screenshot třetího demonstračního příkladu

ict ve školství 24

Obsah dalšího pokračování

V dalším, už předposledním pokračování tohoto seriálu si ukážeme způsob, jakým je možné evaluátory použít při výpočtu normálových vektorů na povrchu Bézierových ploch.

Seznam funkcí zmíněných v této části

glBegin()
glColor()
glEnd()
glEvalCoord2f()
glEvalMesh2()
glMap1f()
glMap2f()
glMapGrid2*()
glTexCoord1()
glVertex()
 

Zkomprimovaná verze článku i s přílohami

Zkomprimovaná verze tohoto článku je umístěna zde.

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.