Thema: Delphi OpenGl-Kurs

Einzelnen Beitrag anzeigen

Benutzerbild von Mr_T
Mr_T

Registriert seit: 7. Jun 2002
Ort: Eilsum
136 Beiträge
 
Delphi 2005 Personal
 
#2

Re: OpenGl-Kurs

  Alt 7. Mär 2004, 15:38
So, nun gibts nach langer Zeit mal wieder ein kleines Update. Und zwar kommt hier eine kleine Ergenzung zum 2. Teil (Praktisch Teil 2b), bei welchem nun entlich die Initialisierung unter Kylix abgehandelt wird. Viel Spaß mit de, Kursteil (wie immer: Original-Text von meiner HP)

------------ Teil 2b ----------


Open Gl - Delphi/Kylix - Kurs Teil 2b: Wie Initialisiert man Open Gl unter Kylix(3)

Einleitung
Hi Leute!
So, nachdem der Kurs nun schon ganze 13 Teile stark ist, kommt nun endlich ein Kursteil, mit
dem sicherlich kaum einer Gerechnet hat: Teil 2b: Initialisieren von Open Gl unter Kylix!
Es war ein wirklich langer weg hier her, denn das Umsetzen von Teilen des Kurses nach
Kylix war schon vor einer halben Ewigkeit geplant, konnte aber leider nicht umgesetzt
werden, weil trotzt Crossplatform – Libary (opengl12.pas) die Initialisierung immer wieder
fehlschlug. Nun aber endlich ist es gelungen Open Gl unter Kylix zum laufen zu bekommen
und das nicht nur mit der OpenGl12.pas, sondern auch mit der neusten Ausgabe der
Opengl1.5-Unit der DGL (dglopengl.pas). Ein großer Dank geht denn nochmals von mir hier
aus an DelphiC aus dem DGL-Team, der dieses Möglich gemacht hat. Von ihm stammen
auch viele Teile vom Quelltext aus diesem Kursteil.
Bevor wir anfangen möchte ich noch ein paar Voraussetzungen für das Entwickeln von Open
Gl – Anwendungen unter Linux hier aufführen:
Das wohl wichtigste ist zunächst mal eine funktionierende 3D – Unterstützung, d.h. ein
geeigneter Treiber für die Grafikkarte. NVidia macht es hier den meisten Leuten mit ihrem
Installer ziemlich einfach: RPM installieren und los geht’s (meistens).
Bei ATI ist die Sache noch recht kompliziert (aber nicht unmöglich), evtl. auch, weil ATI
momentan an sich nur Treiber für FireGl-Karten rausgibt, die aber auch mit allen anderen
Radeon-Karten der 8xxx und 9xxx – Reihe laufen.
Weiterhin wichtig ist natürlich noch Kylix. Absolut ausreichend für unsere zwecke ist auf
jeden Fall mal Kylix 3 Open Edition ... zumindest für unsere Demos reicht das vollkommen.
Man kann es kostenlos auf der Borland – HP runterladen.
Ich selbst habe das ganze hier auf einem Athlon XP 2600+, einer Radeon 9600 Pro und unter
Fedora Core 1 (Kernel 2.4.x, XFree 4.3.X, KDE 3) entwickelt.

Los geht’s!
So, genug geschwafelt, ran ans Werk!
Das erste was wir in unserer frisch erzeugten Kylixanwendung machen müssen (solltet ihr
keine lehre vor euch finden, denn erzeugt eine!) ist, ein Panel auf das Form zu ziehen. Dieses
müssen wir leider machen, weil unter Kylix man aus irgendeinem mir nicht erdenklichen
Grunde nicht direkt aufs Form, sondern nur auf Panels rendern kann. Nur damit Klarheit
besteht: ich nenne dieses Panel immer „render_panel“ .... nur damit ihr wisst, was abgeht.
So, nachdem das Panel da ist, brauchen wir erstmal noch einen Timer. Dieser soll für uns den
Taktgeber spielen (Timer auf „1“ setzen). Zunächst hatte ich noch gehofft, evtl. das Onidle-
Event verwenden zu können, dies ging aber nicht, da es unter Linux offensichtlich anders
gehandhabt wird als unter Windows und damit selbst bei Standszene die Framerates stark
schwanke. So, damit haben wir die CLX-Arbeiten (also den visuellen Teil) abgeschlossen.
Nun müssen wir erstmal unsere Open Gl-Unit und die nötige Hilfsunit, welche die GLXFunktionen
kapselt einbinden. (GLX ist etwas das, was für die Windowsler WGL ist ... also
eine Hilfe, Open Gl auf den Schirm zu bringen):

uses .... , dglGLX, dglOpenGl; Als nächstes brauchen wir nun ein paar Variablen, welche wie unter Windows als private
Eigenschaft der Form deklariert werden und alle Eigenschaften bezüglich dem Render-
Context des Forms beinhalten:
Delphi-Quellcode:
  private
    { Private-Deklarationen }
    OpenGlInitialized : Boolean;
    dpy : PDisplay;
    cx : ^integer;
    vi : PXVisualInfo;
    glwin : XID;
  public
    { Public-Deklarationen }
  end;
...
Nun kann es richtig losgehen!
Nun kommt nämlich das Grauen der Windows-Benutzer dran: die OnCreate-Funktion! Diese
bearbeiten wir nun also:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
OpenGlInitialized := false;
end;
Nanu? Was soll das denn werden? Ist das alles?
Na ja: unter Kylix läuft halt alles ein wenig anders. Irgendwie scheint es Kylix nicht so gut zu
bekommen, wenn man direkt im OnCreate initialisiert. Deshalb verschieben wir dieses auf die
OnShow-Prozedur:
Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
var
  Screen : Integer;
  Attributes : TAttributes;
begin
  if not OpenGlInitialized then //Noch nicht initialisiert? Also los:
  begin
    try //Sicher ist sicher....
      InitOpengl; //OpenGl Laden
      ReadExtensions; //Die Extentions laden
      ReadImplementationProperties;

      dpy := XOpenDisplay(#0); //Ein neues Dispaly zum Rendern öffnen
      Screen := XDefaultScreen(dpy); //Dieses Display verwenden
      Attributes:= GetAttributes(); //Hier können Attribute an
                                            //OGl übergeben werden ... bleibt die
                                            //Klammer lehr, denn werden die Standart
                                                    //Attribute genommen
      vi := glXChooseVisual(dpy, Screen, @attributes[0]); //Unseren Screen nemen
      cx := glXCreateContext(dpy, vi, nil, true); //Den OpenGl-Kontext erzeugen
      glwin := QWidget_winId(render_panel.Handle); //Entgültig unser Panel als
                                                          //Renderpanel festlegen
      if not glXMakeCurrent(dpy, glwin, cx) then //Den Renderkontext aktivieren
      begin
        WriteLn('OpenGl Initialisierung schlug fehl!');
        Exit;
      end;

      glShadeModel(GL_SMOOTH);
      glClearColor(0.3, 0.4, 0.6, 1.0); //Eine etwas nettere Hintergrundfarbe
      glEnable(GL_DEPTH_TEST); //Tiefentest einschalten
      glDepthFunc(GL_LEQUAL);
      glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
      FormResize(nil);
      glLoadIdentity;
      Caption := Caption + ' @ ' + glGetString(GL_RENDERER);
                                                   //Hiermit wird der aktuelle Renderer (Radeon, Geforce
                                                   //oder MESA-Software ausgegeben
      OpenGlInitialized := true;
    except
      WriteLn('OpenGl Initialisierung schlug fehl!')
    end
  end;
end;
So, das war eigentlich schon der größte Teil dieses ganzen Tuts. Nachdem wir das geschafft
haben müssen wir an sich nur noch ein paar Kleinigkeiten erledigen.
So muss natürlich noch die altbekannte OnDestroy-Prozedur her, welche ja den OpenGl-
Kontext wieder schließt:
Delphi-Quellcode:
procedure TForm1.FormDestroy(Sender: TObject);
begin
if dpy <> nil then
 begin
  glXMakeCurrent(dpy,0,0);
  if cx <> nil then
   glXDestroyContext(dpy,cx);
   XCloseDisplay(dpy);
  end;
end;
Und was natürlich auch noch fehlt ist die Onresize-Prozedur (kennt man ja alles aus Teil
2(a)):

Delphi-Quellcode:
procedure TForm1.FormResize(Sender: TObject);
var
  Width, Height : Integer;
begin
  Width := render_panel.Width;
  Height := render_panel.Height;
  glViewport(0, 0, Width, Height); // Setzt den Viewport fr das OpenGL Fenster
  glMatrixMode(GL_PROJECTION); // Matrix Mode auf Projection setzen
  glLoadIdentity(); // Reset View
  gluPerspective(45.0, Width/Height, 1, 100.0); // Perspektive den neuen Man anpassen.
  glMatrixMode(GL_MODELVIEW); // Zurck zur Modelview Matrix
  glLoadIdentity();
end;
Nun sind es nur noch zwei kleine Schritte zu vollständigen OpenGl-Initalisierung unter Kylix.
Zunächst muss nämlich noch das Timer-Event eingefügt werden, da wir sonst ja keinen
Taktgeber für die Render-Prozedur haben:
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if OpenGlInitialized then
  begin
    render;
  end;
end;
Und zu guter letzt muss noch die Render-Prozedur selbst her (man sollte sie im Quelltext über
das Timer-Event schreiben, da ansonsten der Timer evtl. die Render-Prozedur nicht finden
kann:

Delphi-Quellcode:
procedure render;
begin
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //Farb und Tiefenpuffer lschen
 glLoadIdentity;

 glXSwapBuffers(form1.dpy, form1.glwin);
end;
Hier kommt nun die erste (und letzte kleine Überaschung). Leider funktioniert der alte
Swapbuffers-Befehl nämlich unter Linux nicht, was aber nicht Tragisch ist, das die GLXFunktionen
einen passenden Ersatz parat haben.
So, damit ist unsere Initialisierung unter Kylix auch schon fertig und wir können fröhlich auch
unter Linux in die Welt von OGL einsteigen.


Nachwort
So, und schon ist es vollbracht!
Ich hoffe es hat euch allen soviel Spaß gemacht wie mir und wird euch soviel Spaß wie mir
machen, endlich auch unter Linux mit OGl runspielen zu können. Zumindest solltet ihr mit
diesem Kursteil die nötigen Voraussetzungen haben, auch wenn ich zugeben muss, dass ich
mich hier sehr kurz gehalten habe (dieser Kursteil ist in 4 Tagen und das während der
Facharbeits-Zeit entstanden ... mehr Zeit war leider nicht...).
Ein kleines Versprechen habe ich noch: Demnächst gibt es für Teil 5 noch ein kleines
Anhängsel, welches meine selbst geschriebene Texturen-Unit näher erklärt. Bis dahin könnt
ihr euch ja aber schon mal die Demo zu Teil 5 ansehen... normalerweise sollte es echt nicht
schwer sein zu erfassen, wie man unter Linux mit dieser Unit Texturen lädt, besonders weil
ich mir viel Mühe gemacht habe die Bedienung einfach zu gestalten.
Also hoffe ich, dass ihr noch viel Spaß mit OpenGL unter Linux habenwerdet und das ihr
auch nächstes Mal wieder reinschaut.
Eurer
Mr_T
Mein neuer, 13 Teiliger Open GL - Kurs (Samples in Delphi):
www.dcw-group.net
Neu! Ein großer Teil der Demos nach Kylix übersetzt!
Neu! Teil 2b: Initialisierung von OpenGL unter Kylix ist fertig!
  Mit Zitat antworten Zitat