Hlavní navigace

Grafická knihovna OpenGL (2): syntaxe funkcí

Pavel Tišnovský

V minulém dílu jsme si popsali základní vlastnosti knihovny OpenGL. Dnešní díl už bude zameřen více prakticky, protože si ukážeme syntaxi většiny funkcí, které jsou v knihovně OpenGL deklarovány. Dále si řekneme, jaké datové typy se v OpenGL používají, a na závěr bude předveden demonstrační program na vykreslení jednoduchého obrazce.

Syntaxe funkcí deklarovaných v OpenGL

Většina funkcí, které jsou v knihovně OpenGL deklarovány, používá poměrně důmyslnou syntaxi, kdy je již ze jména funkce zřejmé, kolik parametrů je použito a jakého jsou typu. Nejprve si uveďme příklad volání funkce z demonstrační aplikace uvedené v závěru dnešního dílu:

glColor3f(0.0f, 1.0f, 0.0f);

Jméno funkce si můžeme rozdělit na čtyři oblasti, které si v dalším textu popíšeme.

glColor3f(0.0f, 1.0f, 0.0f);

Jméno každé funkce z knihovny OpenGL začíná prefixem (předponou) gl. Podobnou vlastnost mají i funkce z navazujících knihoven. Například všechny funkce z knihovny GLU začínají prefixem glu a u knihovny GLUT je použit prefix glut. Pokud chce tvůrce aplikace zachovat čitelnost a srozumitelnost kódu, neměl by své funkce pojmenovávat se zde uvedenými prefixy.

glColor3f(0.0f, 1.0f, 0.0f);

Za prefixem gl následuje tělo jména funkce, které většinou značí vytvářený předmět (např. Vertex) nebo vlastnost, jež se mění (např. Color). Tělo jména funkce začíná velkým písmenem, a pokud se skládá z více slov, jsou počáteční písmena slov velká (např. ClearColor). Ve funkcích nejsou použita podtržítka a neexistují dvě jména funkcí, která by se lišila pouze ve velikosti písem, protože by to dělalo problémy u programovacích jazyků, které velikosti písma nerozlišují, například Pascalu.

glColor3f(0.0f, 1.0f, 0.0f);

Za tělem jména funkce většinou následuje číslo, které značí počet parametů. Z uvedeného příkladu je tedy zřejmé, že funkce bude mít tři parametry. Pokud funkce nemá žádné parametry, žádné číslo se nepíše (tedy ani 0).

glColor3f(0.0f, 1.0f, 0.0f);

Na závěr je jedním či dvěma znaky uveden typ parametrů (viz další text). U většiny funkcí mají všechny parametry stejný typ, takže typ lze specifikovat. Pokud má funkce více parametrů, z nichž každý je odlišného typu, tyto znaky se neuvádí. Některé funkce existující ve více variantách umožňují místo skupiny parametrů stejného typu předat pole. Potom se uvádí typ současně s písmenemv.

Pro dosažení co nejsnazší přenositelnosti definuje knihovna OpenGL své vlastní datové typy, které se při volání funkcí OpenGL doporučuje upřednostňovat před primitivními datovými typy použitého programovacího jazyka. Tyto nové typy si uvedeme v následující tabulce i s příslušným suffixem (příponou), který je použit při skládání jména funkce.

Tabulka č. 449
suffix datový typ v jazyce C v OpenGL
b 8-bit integer signed char GLbyte
s 16-bit integer short int nebo int GLshort
i 32-bit integer int nebo long int GLint
GLsizei
f 32-bit float float GLfloat
GLclampf
d 64-bit float double GLdouble
GLclampd
ub 8-bit unsigned integer unsigned char GLubyte
GLboolean
us 16-bit unsigned integer unsigned short/int GLushort
ui 32-bit unsigned integer unsigned int/long GLuint
GLenum
GLbitfield

Jak je z předchozí tabulky patrné, je v OpenGL u každého datového typu pevně definovaná bitová délka, což je rozdíl oproti například jazyku C, kde typ int může mít podle použité platformy nebo překladače šířku 16, 32 nebo 64 bitů. U čísel v pohyblivé řádové čárce NENÍ vyžadováno, aby byly reprezentovány podle normy IEEE. Je pouze požadována přesnost srovnatelná s čísly reprezentovanými v normě IEEE o stejné bitové šířce. (Pro zajímavost: novější grafické karty s čipem od firmy nVidia interně pracují s šestnáctibitovými čísly v pohyblivé řádové čárce – tzv. half float. Už tedy neplatí tvrzení, že algoritmy implementované v hardwaru musí pracovat pouze s čísly v pevné řádové čárce.)

Většina deklarativních funkcí v OpenGL existuje ve více verzích, které se liší počtem a typem parametrů, například:

glColor3f(float1, float2, float3);
glColor3b(byte1, byte2, byte3);
glColor4b(byte1, byte2, byte3, byte4);
glVertex2i(int1, int2);
glVertex2d(double1, double2);
glVertex3f(float1, float2, float3);
glVertex4f(float1, float2, float3, float4);

Demonstrační příklad

Pro jednoduchou ukázku vlastností knihovny OpenGL si nyní ukážeme příklad, který budeme v dalších dílech postupně rozšiřovat. Práce s okny a reakce na události od uživatele a systému jsou řešeny pomocí funkcí z knihovny GLUT, která již byla na ROOTovi dříve popsána (odkaz na články o GLUTu).

V tomto demonstračním příkladu pouze otevřeme okno a vykreslíme do něj zelený trojúhelník. Aplikaci lze ukončit stisknutím klávesy ESC. Program reaguje na změnu velikosti okna a na požadavek o překreslení okna. K dispozici je zdrojový kód příkladu naprogramovaného v jazyce C a to i s obarvenou syntaxí.

Tělo programu je rozděleno do několika funkcí, které jsou volány při výskytu určitých událostí. Funkce onResize() je zavolána v případě, že se má změnit velikost okna aplikace. Tato funkce je také zavolána ihned po vytvoření okna. Funkce onDisplay() je zavolána při každém požadavku na překreslení okna. Funkce onKeyboard() se zavolá, když uživatel stiskne některou klávesu generující ASCII kód. A poslední (resp. první :-) je funkce main().

V tomto příkladu se zaměříme na volání příkazů OpenGL, které jsou uvedené ve funkci onDisplay(). Příkaz glClearColor(0.0, 0.0, 0.0, 0.0)specifikuje barvu, kterou se vymaže pozadí okna. Zadávají se čtyři barevné složky (Red, Green, Blue a Alpha), z nichž každá je v rozsahu 0.0–1.0 (0.0 znamená nepřítomnost složky ve výsledné barvě, 1.0 maximální vysvícení). Příkazem glClear(GL_CO­LOR_BUFFER_BIT) vymažeme určité bufery na grafické kartě (více v dalších pokračováních seriálu). Zde se vymaže pouze barvový bufer. Příkazem glColor3f(0.0f, 1.0f, 0.0f) specifikujeme barvu pro další vykreslování ve formátu RGB. V tomto případě byla zvolena čistě zelená barva.

Příkaz glBegin(GL_TRI­ANGLES) zahájí vykreslování trojúhelníků, z nichž každý je specifikován třemi vrcholy. Tyto vrcholy se zadávají příkazem glVertex2i(), kterému předáme 2D souřadnice vrcholu trojúhelníka. Ukončení zadávání vrcholů zajistí příkaz glEnd(), který tvoří příkazové závorky spolu s glBegin(). Tyto příkazy tedy vždy musí tvořit pár. Posledním příkazem je glFlush(), který zajistí provedení všech operací na grafické kartě. Bez uvedení tohoto příkazu by se mohlo stát, že některé objekty by nebyly zobrazeny, protože by zůstaly v grafické pipeline karty.

V Linuxu se překlad a slinkování provede následujícím příkazem:
gcc -o opengl02_1 -L/usr/X11R6/lib opengl02_1.c -lglut -lGL -lGLU -lm -lX11 -lXmu

V příštím dílu si popíšeme základní prvky (primitiva), ze kterých lze skládat složitější dvourozměrné a trojrozměrné objekty.

Našli jste v článku chybu?