OpenGL (1.) - Čtverec s interpolací barvy
OpenGL je grafické rozhrání, ve kterém se dají naprogramovat docela slušné hry i v Delphi a tak si myslím, že byste se sem měli alespoň podívat. Dnes se zaměřím na nastavení a tvorbu základní aplikace pod Delphi. Všechno je popsáno pěkně krok po kroku včetně příkladů a tak myslím, že se to dá pochopit.
Pro zprístupnění kouzel knihovny OpenGL potřebujeme přidat do našeho projektu knihovny GL, Glu, popř. i GLaux
uses GL, GLU;
Device context - obsahuje informace potřebné pro GDI (graphics device interface), součást operačního systému
Render kontext (render context) je potřebný pro každý příkaz prováděný OpenGL.
Prvním krokem inicializace OpenGL je získat device kontext, který obsahuje informace potřebné pro GDI. Pokud bude výstup směřovat do okna, můžeme použít funkci GetDC(Handle). Pak je třeba nastavit pixelový formát získanému device kontextu. Zde specifikujeme vlastnosti OpenGL jako Double buffering, z-buffering, alpha buffering, atd. Když budeme mít device kontext s nastaveným pixelovým formátem, můžeme začít vytvořit rendering kontext, do kterého budou kreslit funkce OpenGL
procedure TForm1.FormCreate(Sender: TObject); begin UhelX := 0; UhelY := 0; UhelZ := 0; X := 0.0; Y := 0; Z := -4.0; DC := GetDC(Handle); SetDCPixelFormat(DC); hrc := wglCreateContext(DC); wglMakeCurrent(DC, hrc); Svetlo; Timer.Enabled := True; end;
Funkce wglCreateContext nám vytvoří nový Render Context. Funkce wglMakeCurrent nastaví daný Render Context jako aktuální.
procedure TForm1.SetDCPixelFormat(DC : HDC);
var PFD : TPixelFormatDescriptor;
nPixelFormat : integer;
begin
FillChar(PFD,SizeOf(PFD),0);
with PFD do
begin
nSize := SizeOf(TPixelFormatDescriptor);
nVersion := 1;
dwFlags := PFD_DRAW_TO_WINDOW or
PFD_SUPPORT_OPENGL or
PFD_DOUBLEBUFFER;
iPixelType := PFD_TYPE_RGBA;
cColorBits := 24;
cDepthBits := 32;
iLayerType := PFD_MAIN_PLANE;
end;
nPixelFormat := ChoosePixelFormat(DC,@PFD);
Assert(nPixelFormat <> 0,PFDError);
SetPixelFormat(DC,nPixelFormat,@PFD)
end;
Jestliže pracujeme s grafikou, určitě se budeme chtít na něco podívat. Následující procedura nám na plochu vykreslí barevný čtverec:
procedure TForm1.Ctverec;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
glTranslatef(X,Y,Z); //pozice kamery
glTranslatef(0,0,0); //střed rotace objektu
glRotatef(UhelX, 1, 0, 0); //rotace objektu po ose X
glRotatef(UhelY, 0, 1, 0); //rotace objektu po ose Y
glRotatef(UhelZ, 0, 0, 1); //rotace objektu po ose Z
glEnable(GL_COLOR_MATERIAL);
glBegin(GL_POLYGON);
glNormal3f(0.0, 0.0, 1.0);
glColor3b(0,0,127);
glVertex3f(1.0, 1.0,0.0);
glColor3b(0,127,0);
glVertex3f(1.0, -1.0,0.0);
glColor3b(127,0,0);
glVertex3f(-1.0,-1.0,0.0);
glColor3b(127,127,0);
glVertex3f(-1.0, 1.0,0.0);
glEnd;
SwapBuffers(DC);
end;
![]() |
Funkcí glClear vyčistíme buffery, potom nastavíme matici zobrazení objektu glMatrixMode a tuto matici načteme funkcí glLoadIdentity. Dále nastavíme rotaci objektu glRotatef a pozici kamery glTranslatef. Mezi příkazy glBegin a glEnd definujemepožadovaný obrazec. Funkcí glNormal3f nastavíme hodnotu normálového vektoru. Určuje se vlastně bod, do kterého míří světelný paprsek, který se odrazil od stěny objektu. Maximální hodnota je 1, minimální -1. Základní hodnoty jsou (0, 0, 1), což znamená, že se paprsek odráží kolmo od přední stěny objektu. Funkcemi glColor3b a glVertex3f nastavíme pozice a barvy bodů čtverce.
Pozn.: Když používáme double buffering, tak OpenGL vše vykresluje na neviditelné místo do paměti (back buffer). Scéna se nezobrazí v okně, dokud my nedáme OpenGL příkaz, který prohodí ukazatel na back a front buffer. To je velmi užitečné, protože se scéna vykresluje mimo obrazovku a celý obraz se objeví naráz a nebliká. Po vykreslení celé tedy stačí napsat:
SwapBuffers(DC);
Nastavení prostoru provedeme podle této funkce:
procedure TForm1.FormResize(Sender: TObject); var PomerStran : GLdouble; begin PomerStran := Width / Height; glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPerspective(30.0, PomerStran, 0.1, 400); glViewport(0, 0, Width ,Height); InvalidateRect(Handle, nil, False); end;
Matici zobrazení objektu glMatrixMode nastavíme na GL_PROJECTION a funkcí glLoadIdentity načteme nastavenou matici. Nyní nastavíme prostor tak, jak bude vidět z pozice kamery pomocí funkce gluPerspective(UhelPohledu, PomerStran, Nejbliz, Nejdal), kde úhel pohledu je zorný úhel kamery, poměr stran je poměr výšky a šířky projekčního plátna, nejmenší vzdálenost, od které je objekt viditelný a nejdelší vzdálenost od které již objekt není viditelný. Funkce glViewport nastavuje velikost zobrazované plochy. Nastavený prostor zobrazíme funkcí InvalidateRect(Handle, nil, False).
Pro vykreslení scény si vytvoříme další procedulu, kterou pojmenujeme Kreslit. Mezi příkazy BeginPaint a EndPaint vypíšeme vše, co chceme, aby bylo vykresleno. V našem případě je zde uvedena jen procedura ctverec, ale nic nebrání abychom přidali další:
procedure TForm1.Kreslit(var Msg: TWMPaint); var ps : TPaintStruct; begin BeginPaint(Handle, ps); Ctverec; EndPaint(Handle, ps); end;
![]() |
Nyní bychom měli upravit zdroják pro korektní ukončení programu touto procedurou:
procedure TForm1.FormDestroy(Sender: TObject);
begin
Timer.Enabled := False;
wglMakeCurrent(0, 0);
wglDeleteContext(hrc);
ReleaseDC(Handle, DC);
if (Palette <> 0) then
DeleteObject(Palette);
end;
Nakonec jsem do zdrojáku přidal pár funkcí pro pohyb a rotace námi vytvořeného čtverce. Pohybuje se pohybem myši a rotace se provádí pohybem myši se stisknutým levým nebo pravým tlačítkem.
procedure TForm1.FormMouseMove(Sender:TObject;Shift:TShiftState;DX, DY: Integer); begin if bool then begin oldx:=dx;oldy:=dy;bool:=false;end; if not stisknuto then begin x:=x+((oldx-dx)); z:=z+((oldy-dy)); end; if stisknuto then uhely:=uhely+round((oldx-dx)); if stisknuto then uhelx:=uhelx+round((oldy-dy)); oldx:=dx;oldy:=dy; end; procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin stisknuto:=true; end; procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin stisknuto:=false; end;
Nakonec dodám, že všechny použité proměnné a procedury musí být deklarovány. A to je asi tak vše, co jsem vám chtěl dnes ukázat. Ještě dodám, že zdrojový soubor toho, co jsme dnes vytvořili je zde (40 kB). Už se chystám na pokračování seriálu o tomto Doufám, že jsem vás tímto článkem moc neodradil ale pokud vydržíte, budete moci všem povídat, že jste již programovali v opravdovém 3D prostředí - v OpenGL.
Vyšlo 18.09.2001, v blogu: 0 1 2 3 4 5 6 7 8
Děkuji, že jste se rozhodl(a) přečíst tento článek. Budu rád i za komentář. Pokud Vás tento článek zaujal a rádi byste jej doporučili ostatním, podpořte mně prosím tím, že věnujete minutku svého času a uděláte mi reklamu na linkuj.cz, vybrali.sme.sk či jagg.cz. Přeji příjemné čtení
Poslední články
- Jak se dostat do BIOSů
- Adobe Photoshop (3.) - Textura vodní hladiny
- Delphi (6.) - Grafika a zvuky
- 3D Studio MAX (5.) - Přízemní mlha ve 3D Studiu MAX
- Delphi (5.) - Zajímavé zdrojáky 2.
- Photoshop Tutoriály (2.) - Temná hvězdná obloha
- OpenGL (2.) - Čtverec s texturou
- OpenGL (1.) - Čtverec s interpolací barvy
- 3D Studio MAX (4.) - Jak vytvořit laser
- Delphi (4.) - Zajímavé zdrojáky
- 3D Studio MAX (3.) - Tvorba 3D krajiny
- Delphi (3.) - Detekce typu procesoru, jeho frekvence a využití
- Delphi (2.) - Práce se soubory, *.ini soubory a registry
- Photoshop tutoriály (1.) - Ohnivé koule
- Delphi (1.) - Jak zobrazit startovací obrázek

