|
Registriert seit: 7. Jun 2002 Ort: Eilsum 136 Beiträge Delphi 2005 Personal |
#1
So - wie versprochen gibts nun auch für dieses Forum mein Open - GL - Anfängertutorial.
es ist in derselben Fassung, wie damals das für das DF: Open Gl in Delphi (Kurztutorial) In meinem mitlererweile 4. DCW-Tutorial geht es um Open Glide in (bzw. unter) Delphi. Ich habe zunächst nur ein Kurztutorial geschrieben, weil die Gesammtmaterie doch recht umfangreich ist und ein ausführlicheres Tut momentan für mich kaum realisierbar ist. In diesem Tut geht es also zunächst um die grundsätzlichen Dinge, die man für die Open Gl Programmierung unter Delphi braucht. Inhalt Einleitung Inizialisierung Das erste Objekt Objekte Animieren - Drehen Downloads Einleitung In diesem (Kurz-)Tutorial geht es also um OpenGl unter Delphi. Da es sich nur um ein Kurztutorial handelt, werde ich nicht alles ausführlich erklären (um den gesammten Umfang der OpenGL-Programmerung darzustellen, braucht man 1000 Seitige Bücher......), sondern ich werde lediglich versuchen, einen leichten Einstieg in das OpenGL - Programmieren unter Delphi zu geben, welcher vorerst nur aus den Grundlegenden Basiks besteht. Es wäre sogar gut denkbar, dass ich irgendwann einmal (wenn ich mehr Zeit habe) noch ein zweites Open-Gl Tutorual schreibe, da in diesem noch einiges fehlt (verschiedene Projektionsmodi, Texturen, weitere Möglichkeiten der bewegung und Animation, verschiedene Lichter, displaylisten für flimmerfreie Scenen und Animationen, usw). Zuerst ist aber das "Fensterformen 2" - Tutorial dran. Inizialisierung Also: Der erste Schritt bei der OpenGL - Programmierung ist die Inizialisierung des OpenGL - Rendering Kontextes (bedeutet so viel wie das Formular zu einer für OpenGl brauchbaren Zeichenfläche zu machen). Leider gibt es verschiedene Auffassungen darüber, wie Open Gl inizialisiert werden soll. Da ich hier nur ein Kurztutorial schreibe, und nicht jeden der nachfolgenden OpenGl Befehler erklären will (würde die meisten Newbies ziemlich verwirren), habe ich eine Art Generalinizialisierung zusammengestellt, in welcher die wichtigsten Eigenschaften (wie z.b. der Tiefentest [mehr Geschwindigkeit] und der Backbuffer [Flimerfrei] aktiviert sind. Diese Inizialisierung können sowohl Newbies und auch Profies mit gutem Gewissen immer verwenden, da er die meisten wichtigkeiten OpenGL beinhaltet (hat gleichzeitig die Konsequenz, dass ich nciht alles erklären brauche, weil es ja eh immer so gemacht werden aollte ![]() also: das erste, was man immer machen sollte, ist Open Gl einzubinden ( uses Windows,.....,OpenGl; - ganz oben im Queltext). Nun brauchen wir ein paar Globale Variablen(! Privat - Variablen...):
Code:
private
mydc : HDC; myrc : HGLRC; myPalette : HPALETTE; dazu kommt noch die Procedure "SetupPixelFormat"(auch im Private-Teil): procedure SetupPixelFormat; Damit hätten wir die wichtigesten Variablen schon mal Gesetzt. Nun muss noch die Prozedur "SetupPixelFormat" eingebaut werden (au backe: ziemlich lang):
Code:
Uf - ist ziemlich lang diese Prozedur.... aber wie gesagt, es ist eine Art Generalinizialisierund, die ihr einfach kopieren könnt
procedure Tform1.SetupPixelFormat;
var hheap : Thandle; ncolors,i : integer; lppalette : plogpalette; byredmask, bygreenmask, bybluemask : byte; npixelformat : integer; pfd : Tpixelformatdescriptor; begin Fillchar(pfd,sizeof(pfd),0); with pfd do begin nsize := sizeof(pfd); 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(myDC, @pfd); SetPixelFormat(myDC, nPixelFormat, @pfd); DescribePixelFormat(myDC, nPixelFormat,sizeof(TPixelFormatDescriptor),pfd); if ((pfd.dwFlags and PFD_NEED_PALETTE) <> 0) then begin nColors := 1 shl pfd.cColorBits; hHeap := GetProcessHeap; lpPalette:= HeapAlloc (hHeap,0,sizeof(TLogPalette)+(nColors*sizeof(TPaletteEntry))); lpPalette^.palVersion := $300; lpPalette^.palNumEntries := nColors; byRedMask := (1 shl pfd.cRedBits) - 1; byGreenMask:= (1 shl pfd.cGreenBits) - 1; byBlueMask := (1 shl pfd.cBlueBits) - 1; for i := 0 to nColors - 1 do begin lpPalette^.palPalEntry[i].peRed := (((ishr pfd.cRedShift) and byRedMask) *255)DIV byRedMask; lpPalette^.palPalEntry[i].peGreen:= (((i shr pfd.cGreenShift)and byGreenMask)*255)DIV byGreenMask; lpPalette^.palPalEntry[i].peBlue := (((i shr pfd.cBlueShift) and byBlueMask) *255)DIV byBlueMask; lpPalette^.palPalEntry[i].peFlags:= 0; end; myPalette:= CreatePalette(lpPalette^); HeapFree(hHeap, 0, lpPalette); if (myPalette <> 0) then begin SelectPalette(myDC, myPalette, False); RealizePalette(myDC); end; end; ![]() So - damit hätten wir schonmal die wichtigste (und längste) Prozedur geschaft. Nun brauchen wir noch eine Prozedur, die diese hier aufruft. Dazu bietet sich natürlich die Form.create - Methode (oder besser: das Ereigniss der Methode) an. Also schreiben wir: (oh nein, nicht schon wieder code)
Code:
Zudem sollten wir uns auchnoch darum Kümmern, dass der Gerätekontext auch wieder Freigegeben wird:
procedure TForm1.FormCreate(Sender: TObject);
begin form1.myDC:= GetDC(Handle); SetupPixelFormat; myRC:= wglCreateContext(myDC); wglMakeCurrent(myDC, myRC); glEnable(GL_DEPTH_TEST); glLoadIdentity; end;
Code:
Nun brauchen wir noch eine Prozedur, die unsere spätere Scene Zeichenet. Dazu richeten wir bei "Form1.onpain" eine neue Prozedur ein:
procedure TForm1.FormDestroy(Sender: TObject);
begin wglmakecurrent(0,0); wgldeletecontext(mydc); releasedc(handle,mydc); end;
Code:
Die eben aufgerufene Prozedur "Objekt" ist die Prozedur, die dazu da ist, ein Objekt zu zeichnen. Allerdings existiert diese Prozedur noch nicht, also fügen wir sie zwichen "SetupPixelFormat" und "Formcreate" ein(ich habe ein paar komentare eingefügt, da diese Prozedur später noch wichig wird):
procedure TForm1.FormPaint(Sender: TObject);
begin objekt; end;
Code:
So damit hätten wir unsere Inizialisierung praktischfertig. Vielleicht ist es aufgefallen, dass ich zwischen "glpushmatix" und "swapbuffers(mydc)" eine Lehrzeile gelassen habe. Dort soll später unser Objekt hin. Darum kümmern wir uns im nächsten Kapitel. Achtung: Führt Opengl-Programme nie im Debugger aus - es fürhrt manchmal zu Fehlern!.
procedure Objekt;
begin glClearColor(0, 0, 0.0, 1); // HintergundFarbe glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //Farb und Tiefenpuffer löschen glMatrixMode(GL_PROJECTION); // Darstellungsmodus = Projektionsmodus glLoadIdentity; glPolygonMode(GL_FRONT, GL_FILL); // Nur Vorderseiten darstellen (schneller) / Füllmodus : gefüllte Objekte glMatrixMode(GL_MODELVIEW); // Koordinatensystem drehen glLoadIdentity; // Setzt alles zurück auf Uhrsprungspunkt(sehr wichtig!)-ansonsten wird die Scene irgendwo dargestellt, aber nicht da, wo sie hin soll glPushmatrix(); SwapBuffers(form1.myDC); //scene darstellen end; Das erste Objekt Nachdem wir diesen ganzen Inizialisierungsschrott endlich hinter uns haben, wollen wir beginnen, Objkete auf den Schirm zu bringen (bislang sieht uns meistens nur ein kleines Schwarzes Fenster an). So nun wollen wir unses ersten OpenGl - Objekt zeichenen: Objekt werden in Opengl immer mit "glbegin(objekttyp)" eingelitet und es hört immer mit "glend" auf. Das einfachste 3d - Objekt in OpenGl (ich werde in diesem Tut nur 3d beachten, da 2d kaum wen mehr interessiert) ist ohne Zweifel der Würfel. Wir wollen nun also einen würfel zeichnen: Dazu schreiben wir volgenden Quelltext in die "Objekt" - Prozedur undzwar zwischen "glPushmatrix();" und "SwapBuffers(form1.myDC);":
Code:
Zur Erklärung: Ein Opengl-Würfel wird immer durch seine 6 Seiten gebildet. Diese Seiten werden wiederum durch ihre 4 Eckpunkte gebildet. Diese Echpunkte werden immer im Uhrzeigersinn angegeben (kann man am besten an der "Vorderseite sehen"). Dieses hat volgenden Grund: wenn OpenGL eine Fläche betrachtet, deren Punkte im Uhrzeigersinn stehen, dann betrachtet es diese Seite als vorne (demnach von der anderen Seite als hinten). In unserer Definition haben wir angegeben, dass nur die Vordersiten gezeichnet werden sollen, um Rechenpower zu sparen.
glBegin(GL_QUADS); //dieser Befehl zeichnet einen Würfel.
glVertex3d(0.5, -0.5, 0.5); //Linke Seite glVertex3d(-0.5, -0.5, 0.5); glVertex3d(-0.5, -0.5, -0.5); glVertex3d(0.5, -0.5, -0.5); glVertex3d(-0.5, -0.5, -0.5); //Rückseite glVertex3d(-0.5, 0.5, -0.5); glVertex3d(0.5, 0.5, -0.5); glVertex3d(0.5, -0.5, -0.5); glVertex3d(0.5, -0.5, -0.5); //Oberseite glVertex3d(0.5, 0.5, -0.5); glVertex3d(0.5, 0.5, 0.5); glVertex3d(0.5, -0.5, 0.5); glVertex3d(-0.5, -0.5, 0.5); //Vorderseite glVertex3d(-0.5, 0.5, 0.5); glVertex3d(0.5, 0.5, 0.5); glVertex3d(0.5, -0.5, 0.5); glVertex3d(-0.5, -0.5, 0.5); //Boden / Unterseite glVertex3d(-0.5, 0.5, 0.5); glVertex3d(-0.5, 0.5, -0.5); glVertex3d(-0.5, -0.5, -0.5); glVertex3d(-0.5, 0.5, 0.5); //Rechte Seite glVertex3d(0.5, 0.5, 0.5); glVertex3d(0.5, 0.5, -0.5); glVertex3d(-0.5, 0.5, -0.5); glEnd(); Wenn wir nun die Szene starten, sehen wir einen weißen Würfel in unserem Fenster (besser: wir sehen seine Vorderseite). Insbesondere das Weiß sieht allerdings ziemlich pfade aus: unserer Würfel braucht eine Farbe. In OpenGl gibt es zwei Möglichkeiten Farben zu setzen: den Befehl "glcolor3f" und "glcolor4f". Der erste verlangt 3 Parameter. Bei diesen Parametern handelt es sich um Float-Werte, die zwischen 0 und 1 liegen. Diese definieren die Farbe (RGB). Bei "glcolor4f" ist es genau das selbe, blos das als 4. Parameter noch ein Transparenzwert benötigt wird - in unserem Beispiel brauchen wir aber keine Transparenz. Wir schreiben nun also volgende Zeile vor "glBegin(GL_QUADS);":
Code:
Und schwups: Unserer Würfel wird Quietschgelb. Es ist insgesamt etwas ungewohnt, mit Werten zwischen 0 und 1 arbeiten zu müssen, aber ich glaube, das wichtigtste bekommt man hin ( glcolor3f(1,0,0) = rot , glcolor3f(1,1,0) = gelb , glcolor3f(0,1,0) = grün , glcolor3f(0,1,1) = blaugrün , glcolor3f(0,0,1) = blau , glcolor3f(1,0,1) = lila , glcolor3f(1,0.5,0) = orange) .
glcolor3f(1,1,0);
Allerdings ist das ganze noch sehr langweilig, weil wir unseren Würfel nur von vorne sehen...naja: da werden werden wir uns im nächsten Kapitel drum kümmern. Objekte Animieren - Drehen Es gibt viele Methoden, um Opengl - Objekte zu bewegen, bzw zu animieren. in diesem Tutorial werden wir uns aber nur mit dem "Drehen" befassen. Objekte in Oüpengl dreht man über den Befehl "glrotate()". Dieser Befehl verlangt 4 Parameter. Der erste gibt an, um wieviel Grad gedreht werde soll. Die anderen definieren eine Achse, um die gedreht werden soll. So dreht der Befehl "glrotate(45,1,0,0);" die nachfolgende Szene um 45 Grad um die X-Achse. Ich will das ganze in einem Beispiel verdeutlichen: Wir legen zwei globale Variablen "rotx" und "roty" an. Beide sind vom Typ "integer":
Code:
Schreiben wir zwischen "glcolor3f" und "glbegin(...)" folgende Zeilen, die unseren Würfel drehen sollen:
var
Form1: TForm1; rotx : integer; roty : integer;
Code:
glrotate(rotx,1,0,0); //drehung um die x-achse
glrotate(roty,0,1,0); //drehung um die y-achse Nun brauchen wir noch eine Methode, mit denen wir "rotx" und "roty" ändern können. Wir bearbeiten also das "onkeydown"-ereigniss unbseres Fensters:
Code:
Und siehe da: Wenn wir nun unsere Scene starten, können wir unseren Würfel mit den Pfeiltasten drehen. Allerdings sieht die vordere ecke immer etwas merkwürdig aus (wird nicht richtig dargestellt). Dies hat damit zu tun, dass wir noch kein Licht haben, aber diesen Mangel zu beheben, würde den Umfang dieses Tutorials Sprengen. Wie zu anfang schon gesagt: es wäre gut denkbar, das ich irgendwann nochmal ein zweites OpenGL - Tutorial schreibe - evtl muss für Lichter sogar ein extra Tut her. Ich hoffe es hat dennoch gefallen und war nicht zu schwer zu verstehen.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin if key = vk_down then begin rotx := rotx+1; end; if key = vk_up then begin rotx := rotx-1; end; if key = vk_right then begin roty := roty+1; end; if key = vk_left then begin roty := roty-1; end; repaint; end; Downloads ![]() ![]() März/April 2002: ![]() Geschrieben für ![]() ********Doppelpost gelöscht********* FuckRacism (Edited by Daniel B) Einrückungen, Fehlerbehebung |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |