Na ·vod bych cht∞l pod∞kovat Bernymu za sebe i za vÜechny, kter²m tento Φlßnek velice pomohl, a kte°φ si myslφ, ₧e d∞lat programy v²hradn∞ pro komerΦnφ Wokna nenφ tou sprßvnou cestou.
Woq m∞ po₧ßdal, abych napsal tutorißl pro pou₧φvßnφ OpenGL pod knihovnou SDL. Je to m∙j prvnφ tutorißl, tak₧e doufßm, ₧e se bude lφbit. Zkusφme vytvo°it k≤d, kter² bude odpovφdat druhΘ lekci "normßlnφch" tutorißl∙. Zdrojov² k≤d je "oficißlnφ" NeHe port druhΘ lekce do SDL. Pokusφm se popsat, jak se vytvß°φ okno a v∞ci okolo.
Nejd°φve n∞co o tom, co je SDL. SDL, univerzßlnφ knihovna, slou₧φ pro tvorbu her. Znßte-li Allegro, tak SDL je mu trochu podobnΘ. Bylo napsßno v C(/C++) a jeho domovskΘ prost°edφ bylo Linux. Nynφ ale existuje i pod BeOS, MacOS, Windows, QNX, AmigaOS, PS2,.... Obsahuje zßkladnφ API pro vytvo°enφ okna, 2D grafiku, vφcevlßknovΘ programovßnφ, obsluhu klßvesnice, krysy a joysticku, p°ehrßvßnφ videa a zvuk∙. Ke knihovn∞ jsou jeÜt∞ podp∙rnΘ knihovniΦky pro naΦφtßni rozmanit²ch grafick²ch formßt∙, pro lepÜφ ozvuΦenφ (mp3, ogg,..) a sφ¥ovΘ slu₧by pro multiplayer. P°φmo podporuje vyu₧itφ OpenGL, kterΘ samo o sob∞ manipulaci s okny, komunikaci se systΘmem a vÜechnu prßci okolo neumφ a tudφ₧ ned∞lß. K≤d kter² vytvo°φte v SDL m∙₧ete velice snadno p°enΘst jinam jednoduch²m p°ekompilovßnφm (bude to fungovat, pokud nepφÜete jako Φu≥ata). SDL nenφ jen n∞jakß malß knihovniΦka, ale pou₧φvajφ ji i komerΦnφ hry. V∞tÜina her od Lokisoft (portujφ hry pod Linux) je nad SDL a Unreal Tournament 2003 takΘ. NejlepÜφ bude, pokud navÜtφvφte domovsk² web - http://www.libsdl.org/. Jsou tam vÜemo₧nΘ helpy, nßvody, manußly a takΘ vystaveny prßce lidφ, kte°φ SDL pou₧φvajφ; pßr dφlek i z ╚R.
Ne₧ zaΦneme, ujist∞te se, ₧e mßte knihovnu SDL. Pokud ne, navÜtivte v²Üe uvedenou adresu a stßhn∞te si soubory pro vaÜi konkrΘtnφ platformu.
A te∩ u₧ se vrhneme na programovßnφ. Nejd°φve vlo₧φme hlaviΦkovΘ soubory. Mo₧nß se to zdß na prvnφ pohled jako Üφlenost, ale vy°eÜφme p°enßÜenφ k≤du na r∙znΘ OS. Proto doporuΦuji toto vklßdßnφ nechat tak, jak je.
#ifdef WIN32 // Pokud se bude kompilovat program po Windows
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // HlaviΦkov² soubor pro Windows
#endif
#if defined(__APPLE__) && defined(__MACH__) // Pokud se bude kompilovat program pro Apple
#include <OpenGL/gl.h> // HlaviΦkov² soubor pro OpenGL32 knihovnu v Applu
#include <OpenGL/glu.h> // HlaviΦkov² soubor pro GLu32 knihovnu v Applu
#else
#include <GL/gl.h> // HlaviΦkov² soubor pro OpenGL32 knihovnu
#include <GL/glu.h> // HlaviΦkov² soubor pro GLu32 knihovnu
#endif
#include "SDL.h" // HlaviΦkov² soubor pro SDL
Vytvo°φme funkci na inicializaci OpenGL (smφchanΘ InitGL() a ResizeGLScene() z klasick²ch tutorißl∙). NaÜφm cφlem nenφ rozebφrat OpenGL, ale spφÜe vysv∞tlit SDL. Pro detaily se podφvejte do druhΘ lekce.
void InitGL(int Width, int Height) // Tuto funkci volßme hned po vytvo°enφ okna pro inicializace OpenGL
{
glViewport(0, 0, Width, Height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // ╚ernΘ pozadφ
glClearDepth(1.0); // Povolφme mazßnφ pozadφ
glDepthFunc(GL_LESS); // Vybereme typ Depth Testu
glEnable(GL_DEPTH_TEST); // Povolφme Depth Test
glShadeModel(GL_SMOOTH); // Povolφme Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Resetujeme projekΦnφ matici
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // VypoΦφtßme pom∞r okna
glMatrixMode(GL_MODELVIEW);
}
Vykreslovßnφ...
void DrawGLScene() // Hlavnφ vykreslovacφ funkce
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Vymazßnφ obrazovkovΘho a hloubkovΘho bufferu
glLoadIdentity(); // Reset matice pohledu
glTranslatef(-1.5f,0.0f,-6.0f); // Posun o 1.5 doleva a o 6 do hloubky
// Nakreslφ troj·helnφk
glBegin(GL_POLYGON);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
glTranslatef(3.0f,0.0f,0.0f); // Posuneme se o 3 doprava
// Nakreslφ Φtverec
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
Na konci provedeme drobnou zm∞nu. Zavolßme funkci SDL_GL_SwapBuffers(), kterß zajistφ, ₧e se na obrazovce objevφ vÜe, co jsme ve funkci DrawGLScene() nakreslili. V klasick²ch tutorißlech najdete SwapBuffers() ve WinMain() po volßnφ tΘto funkce.
SDL_GL_SwapBuffers(); // Prohozeni bufferu, aby se zobrazilo, co jsme nakreslili
}
Äe se funkce main() provßdφ po spuÜt∞nφ programu jako prvnφ doufßm vφte :-] Le₧φ zde v∞tÜina SDL k≤du. Nejprve provedeme inicializaci a pak cyklujeme dokola v jednoduchΘ smyΦce zprßv. Dßvejte si pozor, aby deklarace main() byla p°esn∞ takovß, jak mß b²t - nikdy nevynechßvat argumenty a nßvratovou hodnotu.
int main(int argc, char **argv) // Prost∞ main() :-)
{
int done; // UkonΦovacφ prom∞nnß
Inicializace knihovny se musφ zavolat jako prvnφ p°ed vÜφm ostatnφm. SDL_INIT_VIDEO znamenß, ₧e budeme chtφt inicializovat v²stup na obrazovku. M∙₧e se kombinovat i s dalÜφmi jako t°eba timerem, audiem,... Knihovna SDL nßm umo₧≥uje pou₧φvat stdout a stderr pro textov² v²stup. V Linuxu vypisuje na terminßl, ve windows vytvo°φ soubory stdout.txt a stderr.txt (v p°φpad∞, ₧e do nich nic nezapφÜete je pak op∞t sma₧e).
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) // Inicializace SDL s grafick²m v²stupem
{
fprintf(stderr, "Selhala inicializace SDL: %s\n", SDL_GetError());
exit(1);
}
Te∩ m∙₧eme vytvo°it okno aplikace. Mßme k tomu funkci SDL_SetVideoMode. Prvnφ dva parametry jsou rozm∞ry okna, dalÜφ parametr urΦuje barevnou hloubku (0 zachovßvß souΦasnou). Poslednφ parametr je kombinacφ r∙zn²ch flag∙. Pokud chceme po₧φvat OpenGL, musφme zadat SDL_OPENGL (nebo SDL_OPENGLBLIT). Pokud chcete fullscreen, m∙₧ete p°idat flag SDL_FULLSCREEN. V X11 (Linuxu) m∙₧ete p°epφnat mezi fullscreenem a oknem svobodn∞ kdykoliv se vßm zachce volßnφm funkce SDL_WM_ToggleFullScreen(), ale ve Windows si v SDL_SetVideoMode() jednou vyberete a to vßm pak z∙stane. Proto₧e jsme inicializovali SDL, musφme ho v p°φpad∞ erroru takΘ ukonΦit. Mß to na starosti funkce SDL_Quit().
if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL) // Vytvo°enφ OpenGL okna 640x480
{
fprintf(stderr, "Neni mozne vytvorit OpenGL okno: %s\n", SDL_GetError());
SDL_Quit(); // UkonΦenφ SDL
exit(2);
}
Nastavφme titulek okna. M∙₧eme p°idat i ikonku, ale proto₧e ₧ßdnou nemßme, pou₧ijeme NULL.
SDL_WM_SetCaption("Jeff Molofee's GL Code Tutorial ... NeHe '99", NULL); // Titulek okna
InitGL(640, 480); // Inicializace OpenGL
Hlavnφ cyklus programu. Pro opuÜt∞nφ programu pou₧ijeme prom∞nnou done (deklarovanß na zaΦßtku main(), kterou testujeme v ka₧dΘm pr∙b∞hu hlavnφm cyklem.
done = 0; // JeÜt∞ nekonΦit
while (!done) // Hlavnφ cyklus programu
{
DrawGLScene(); // Vykreslenφ scΘny
Obsluha udßlostφ by m∞la p°ijφt do zvlßÜtnφ funkce (analogie WndProc() z Windows), ale nebudeme jednoduch² k≤d komplikovat. Nejprve vytvo°φme prom∞nou typu SDL_Event. Pak pro naΦtenφ zprßv volßme v cyklu SDL_PollEvent(). Dokud p°ichßzejφ udßlosti, tak se jimi zab²vßme. Tentokrßt zareagujeme pouze na po₧adavek ukonΦenφ pomocφ klßvesy ESC. P°esuny okna, zm∞na jeho velikosti ap. se d∞jφ automaticky.
SDL_Event event; // Prom∞nnß zprßvy
while (SDL_PollEvent(&event)) // Zpracovßvat zprßvy
{
if (event.type == SDL_QUIT) // Zprßva o ukonΦenφ
{
done = 1; // UkonΦit hlavnφ cyklus
}
if (event.type == SDL_KEYDOWN) // Zprßva o stisku klßvesy
{
if (event.key.keysym.sym == SDLK_ESCAPE) // Klßvesa ESC
{
done = 1; // UkonΦit hlavnφ cyklus
}
}
}
}
Na konci u₧ jen ukonΦφme SDL.
SDL_Quit(); // UkonΦenφ SDL
return 1;
}
Pro kompilaci tutorißlu v Linuxu m∙₧eme pou₧φt p°φkaz
gcc -Wall lesson02.c `sdl-config --libs --cflags` -o lesson02
Ve Windows a Visual C++ je zprovozn∞nφ maliΦko komplikovan∞jÜφ. Vychßzφm z jednoho Φlßnku o SDL, kter² napsal FrantiÜek Jahoda, a kter² jsem kdysi stßhl z http://www.builder.cz/. Pov∞tÜinou CTRL+C & CTRL+V :-] V prost°edφ Microsoft Visual C++ postupujte takto:
#pragma comment (lib,"opengl32.lib")
#pragma comment (lib,"glu32.lib")
#pragma comment (lib,"glaux.lib")
#pragma comment (lib,"sdl.lib")
#pragma comment (lib,"sdlmain.lib")
napsal: Bernard Lidick² - Berny
maliΦko poupravoval, p°epsal do HTML a dopsal zßv∞r pro zprovozn∞nφ ve Windows: Michal Turek - Woq