AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi OpenGL für Anfänger
Tutorial durchsuchen
Ansicht
Themen-Optionen

OpenGL für Anfänger

Ein Tutorial von Mr_T · begonnen am 12. Jun 2002 · letzter Beitrag vom 28. Mai 2009
Antwort Antwort
Benutzerbild von Mr_T
Mr_T
Registriert seit: 7. Jun 2002
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 ). Genug der Worte - los gehts:
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:
 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;
Uf - ist ziemlich lang diese Prozedur.... aber wie gesagt, es ist eine Art Generalinizialisierund, die ihr einfach kopieren könnt .
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:
 procedure TForm1.FormCreate(Sender: TObject);
begin
  form1.myDC:= GetDC(Handle);
  SetupPixelFormat;
  myRC:= wglCreateContext(myDC);
  wglMakeCurrent(myDC, myRC);
  glEnable(GL_DEPTH_TEST);
  glLoadIdentity;
end;
Zudem sollten wir uns auchnoch darum Kümmern, dass der Gerätekontext auch wieder Freigegeben wird:

Code:
 procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglmakecurrent(0,0);
  wgldeletecontext(mydc);
  releasedc(handle,mydc);
end;
Nun brauchen wir noch eine Prozedur, die unsere spätere Scene Zeichenet. Dazu richeten wir bei "Form1.onpain" eine neue Prozedur ein:

Code:
 procedure TForm1.FormPaint(Sender: TObject);
begin
  objekt;
end;
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):

Code:
 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;
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!.


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:
 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();
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.
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:
glcolor3f(1,1,0);
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) .
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:
var
  Form1: TForm1;
  rotx : integer;
  roty : integer;
Schreiben wir zwischen "glcolor3f" und "glbegin(...)" folgende Zeilen, die unseren Würfel drehen sollen:

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:
 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;
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.


Downloads



Dieses Tutorial als HTML-Datei
Das Beispielprogramm




März/April 2002: Mr_T
Geschrieben für DCW-Group

********Doppelpost gelöscht********* FuckRacism
(Edited by Daniel B) Einrückungen, Fehlerbehebung
 
Benutzerbild von Pyr0cracker
Pyr0cracker

 
Delphi 7 Personal
 
#2
  Alt 20. Nov 2002, 12:00
juhuu sitzt hier in der schule und habe dein tutorial gleich mal runtergeladen und auf diskette => gezogen.
werde es zuhause mal testen.
PS: bin noch blutiger anfänger aber nich so schlimm

Pyr0cracker
Dorian Vasco
  Mit Zitat antworten Zitat
Benutzerbild von Mr_T
Mr_T

 
Delphi 2005 Personal
 
#3
  Alt 29. Nov 2002, 23:21
Ich muss dir eines ganz ehrlich sagen: es ist etwas her, das ich dieses Tut geschriben habe und demnach sind meines Wissenstandes nach auch einige Dinge überhohlungsfällig .... ich habe nun auf na Hp, wo ich Member bin nen ganzen Open GL - Delphi - Kurs gestartet (guckt in meine Userdaten und dann auf meine HP) .... damit dürftet ihr besser bedient sein, als mit dem Kurztut (war eh sehr knapp irgendwie.......)
Edit:
ach ne... stelle gerade fest, das der Link aus seit einiger Zeit in meiner sig steht .... hatte ich ganz vergessen............
  Mit Zitat antworten Zitat
Howard
 
#4
  Alt 7. Jan 2003, 11:31
Tach Mr.T

erstma dankeschön für das tutorial

leider muss ich sagen das wenn ich das fertig erstellte ausführe, es zwar den gelben würfel zeichnet und man ihn auch drehen kann...aber sobal man eine cursor-taste drückt färbt sich das bild kurz weiß, sprich es flackert beim drehen

woran könnt das liegen?

gruß Howard
  Mit Zitat antworten Zitat
Benutzerbild von Pyr0cracker
Pyr0cracker

 
Delphi 7 Personal
 
#5
  Alt 8. Jan 2003, 11:08
moin howard
könnte das mit dem flackern am doublebuffered:=false liegen?
ich weiss nicht wie das bei opengl ist aber sonst ist das die lösung
Gruß
Dorian Vasco
  Mit Zitat antworten Zitat
Benutzerbild von mschaefer
mschaefer

 
Delphi XE3 Enterprise
 
#6
  Alt 13. Aug 2008, 22:35
Kannst Du das Beispiel in den Anhang legen. Der Link geht ins Leere.
Martin Schaefer
  Mit Zitat antworten Zitat
Benutzerbild von Spiderpig_GER_15
Spiderpig_GER_15

 
Delphi 7 Personal
 
#7
  Alt 27. Mai 2009, 01:12
kann ich nur recht geben, bin scharf auf dein Tut, aber dein Hompage Link in deiner Note funktioniert leider nicht...
  Mit Zitat antworten Zitat
Benutzerbild von Mithrandir
Mithrandir
 
#8
  Alt 27. Mai 2009, 08:05
Sein letzter Besuch in der DP war vor 3 Jahren... Ich denke nicht, dass du dir da noch große Hoffnungen machen solltest..
米斯蘭迪爾
  Mit Zitat antworten Zitat
Benutzerbild von Spiderpig_GER_15
Spiderpig_GER_15

 
Delphi 7 Personal
 
#9
  Alt 27. Mai 2009, 10:04
verdammt, guter Tipp...

Dann geh ich jetzt irgendwo hin verzweifeln... Die Tuts von DGL find ich nämlich nicht so genial

Naja, man nimmt was man kriegt

Gruß Spiderpig
  Mit Zitat antworten Zitat
pierredrks
 
#10
  Alt 28. Mai 2009, 07:18
Hier gibt es die Tuts noch.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz