AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi OpenGl-Kurs
Tutorial durchsuchen
Ansicht
Themen-Optionen

OpenGl-Kurs

Ein Tutorial von Mr_T · begonnen am 2. Jun 2003 · letzter Beitrag vom 21. Apr 2005
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von Mr_T
Mr_T
Registriert seit: 7. Jun 2002
Hi!
Es liegt nun ja schon etwas länger zurück, dass ich hier meinen OpenGl-Kurzkurs gepostet habe und ich habe mitlererweile festgestellt, dass so mancher Fehler drinne war. Da ich nun aber auf meiner HP bereits vor einiger Zeit einen kompletten Kurs gestartet habe (zu diesem Zeitpunkt bestehend aus 8 Teilen), habe ich beschlossen als wiedergutmachung die ersten 3 Teile hier zu posten (praktisch als Wiedergutmachung für das verkorkste Kurztut.....)
Leider muss ich euch sagen, dass die ganzen Bilder hier rausgefallen sind... naja: muss man mit leben (bzw: wenn es euch gefällt, könnt ihr euch ja auf www.dcw-group.net in der Coding-Sec die DOC-Files mit Bildern oder auch die Samples downloaden... Naja: viel spaß beim Reinschnuppern:
(falls einigem einige Formulierungen im Bezug auf "Wochen" merkwürdig vorkommen: es handelt sich hier um die unveränderten Original-texte und da habe ich mich teilweise auf die Erscheinungsdaten der Tuts bezog
en....)



------------ Teil 1 ----------

Open Gl -Delphi ? Kurs Teil 1: Was ist Open Gl


Einleitung

So Leute... es ist mal wieder soweit: meine neuen Tuts rücken an Allerdings ist diesmal einiges anders: Es ist nicht ein Tut, sondern ein ganzer Kurs! Das bedeutet: so etwa alle zwei Wochen erscheint ab nun ein weiterer Teil dieses Kurses, in dem es um die Open Gl ? Programmierung unter Delphi gehen soll. Ich fand diesen Schritt notwendig, da das Kurztutorial von mir bei weitem nicht die Möglichkeiten der Open Gl ? Programmierung aufgezeigt hat und, weil da die Initialisierung, die Grundlagen und die Story von Open Gl doch sehr knapp gekommen sind. Nun damit wollte ich hiermit Schluss machen, bloß ist mir dabei meine Planung derartig umfangreich geworden, dass ich das Ganze in Kurse aufspalten musst, die uns noch bis Anfang 2003 begleiten dürften... aber nun gut: lasst uns anfangen (ein großer Schritt für mich, aber ein kleiner ... ach Blödsinn... die Menschheit gammelt das hier doch gar nicht )

Was ist Open Gl

An sich ne sehr gute Frage... was ist Open Gl eigentlich???
In vielen Spielen sieht man oftmals so einen netten kleinen Button, auf dem steht meist ?Software-Rendering? und oft ist daneben einer, der heißt ?Open Gl?. Die Meisten werden nach einiger Zeit feststellen, das man mit der Open Gl ? Einstellung meist besser fährt bzw. eine schönere Spielwelt erzeugt (bis auf die Armen, die null Peilung haben, und bloß nichts verändern wollen... ?läuft doch? *g*)
Damit hätten wir so das Gröbste auch schon erfasst!
Wie viele nun bereits festgestellt haben, ist Open Gl eine Grafikschnittstelle, dass heißt, eine Art und Weise, mit der man Grafiken auf diesen eckigen Kasten vor euch bringen kann (bei mir ist das ein grauer Röhrenbildschirm... ein 17 Zöller)
Nun... was ist nun aber an Open Gl anders, als an diesem ?Software-Rendering?? Nun das ist an sich schnell erklärt: Open Gl ist ein Standart, der von praktisch allen 3d ? Grafikkarten unterstützt wird, daher ist es auch deutlich schneller, da es praktisch eine Norm darstellt.
Ausgedacht hat sich diese ?Norm? die Firma ?Silicon Graphics Inc?... und das im Jahre 1988/89!!! Damals hieß das Ding aber noch ?IRIS GL? und lief nur auf den Workstations von Silicon Graphics. Aber dann wurde Silicon Graphics von dem langsam größer werdenden Anteil von Windows dazu veranlasst einen Portablen, also für fast alle Betriebssysteme brauchbaren Grafikstandart zu entwerfen... und daher geschah es: Open Gl erblickte das Licht der Welt und zwar auf der ersten ?Win. 32 Entwicklerkonferenz? in San Francisco am 19.06.92. Zu diesem Zeitpunkt war z.B. Windows NT noch in der Beta 3.1 .
Seit dem gibt es also Open Gl schon, aber es ist bis heute nur bis zur Version 1.4. weiterentwickelt worden... die meisten kommen sogar mit der Urversion 1.0 klar... das liegt unter anderem daran, dass in Open Gl von vorne herein Dinge eingebaut waren, welche die damalige Hardware unter keinen umständen verarbeiten konnte... Gott sei dank, denn daher blieben viele Updates (wie sie bei Microsofts Direct X an der Tagesordnung sind) aus.
Und das schönste: Open Gl wurde wie gesagt als Portable Schnittstelle konzipiert. Das heißt: man findet Open Gl auf allen Linux und Unix ? Systemen und für uns wichtig auch auf den Windows NT Systemen (ab Version 4.0) und natürlich auch auf den Windows 9x Systemen (ab Windows 95 b... Für alle die es unter Windows 95 a nutzen sollen: rennt zu eurem Nachbarn und holt euch auf Diskette die ?OpenGl.dll?... dann läuft es auch bei euch)

So, was kann man nun aber mit Open Gl machen?
Na ja: es ist an sich sehr einfach ein Beispiel zu finden...
Drückt doch bitte einmal auf Start, wählt nun ?Programme? und startet dieses nette Spielchen, welches sich ?Quake 3 Arena? nennt...
Wie? Ihr seit ehrliche Menschen und habt kein Q 3? Nahgut... dann zockt ne runde ?Counter Strike? das ist auch beweiß genug, was man mit Open Gl alles so anstellen kann... nun staunt ihr, oder?

Viele werden sich jetzt fragen: kann ich das auch?
Die Antwort ist: ?Jein?
An sich kann es jeder, aber jetzt noch nicht
Nein: lasst uns ehrlich sein: natürlich ist es irgendwie möglich, so was auch zu machen, aber es ist ein langer Weg dorthin und an solchen Spielen haben zig Entwickler schon einiges Zeit gearbeitet. Aber ganz ehrlich: wenn ihr eure Ansprüche etwas zurücksetzt, werdet ihr in diesem Kurs ne Menge lernen... z.B. wie man mit der richtigen Technik in wenigen Minuten ne einigermaßen passable Landschaft gestallten kann, usw.










------------ Teil 2 ----------


Open Gl - Delphi ? Kurs Teil 2: Wie Initialisiert man Open Gl in Delphi

Einleitung
Ach Leute, ist es schon wieder soweit?
Schon wieder 2 Wochen rum? Na ja... dann werde ich wohl müssen...
In diesem Kursteil wollen wir also Open Gl in Delphi initialisieren, d.h., dass wir Open Gl klar machen wollen, dass es in unserem Fenster etwas zeichnen kann... mehr nicht!
Ich weiß, das dieses für extrem wissbegierige sehr wenig ist, aber ich möchte auch ausreichend genug auf Kleinigkeiten eingehen können, damit nicht wieder so was Unvollständiges wie in meinem Kurztut dabei rauskommt.
Leider muss ich auch sagen, das dieser Teil des Kurses der ziemlich Trockenste und Langweiligste wird. An sich ist die Initialisierung eh jedes mal das selbe... für alle andren Teile des Kurses würde es auch reichen, wenn ihr euch einfach das Sample runterladen würdet und es als Grundgerüst für alles andre verwenden würdet. Wer wirklich lust hat und sich nicht entmutigen lässt, der darf ja ruhig auch lesen (aber hinterher nicht entnervt aufgeben!!!)

Wie initialisiert man Open Gl

Dann wollen wir also...
Zunächst haben wir nur ein sehr leeres Projekt vor uns, ganz ohne eigenen Code...

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

end.

Soweit, so gut... das sollte nun zunächst jeder vor sich sehen.
Der erste Schritt besteht nun darin, an den Uses ? Teil hinter ?Dialogs? noch die Unit ?Opengl? einzutragen, damit Delphi die nötigen Dinge erst mal parat hat.
Nun benötigen wir ein paar Variablen, welche wir in den Privat ? Bereich schreiben. Es handelt sich bei den ersten Zwei um Variablen, welche bei der Erstellung des OGL Kontextes benötig werden. Die dritte ist die Variable für die Farbpalette. Zudem müssen wir schon mal die Prozedur mit Namen ?SetupPixelFormat? hier einragen. Sie wird später gebraucht, da in ihr die meisten Open Gl ? Einstellungen vorgenommen werden. Das Ganze sollte nun so aussehen (Veränderungen sind rot markiert):

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, opengl;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
   myDC : HDC;
   myRC : HGLRC;
   myPalette : HPALETTE;
   procedure SetupPixelFormat;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}


procedure TForm1.SetupPixelFormat;
begin

end;

end.

So Leute: weiter im Programm! Nun benötigen wir noch ein Paar kleine Dinge:
1) wir legen eine kleine Prozedur Namens ?Render? an (die kann auch anders heißen, aber ich möchte das ganze Normieren, d.h. ich möchte, dass ich nicht immer sagen muss ?ruft nun eure Rendering ? Methode auf?... Ihr wisst schon, was ich meine
2) Wir brauchen die 2 Prozeduren ?Form.create? und ?Form.destroy?. In die erste soll später die eigentliche Initialisierung und die andere Brauchen wir, um den Rendering ? Kontext (das Ding, was Open Gl sagt, wo es zeichnen soll) wieder freizugeben.
3) Und zuletzt: die OnRezise ? Prozedur, damit wir auch ne Anständige Sichtweise bekommen (haben wir dich nicht schon???)

So... wenn wir das haben, dann könnten wir uns ja an die ganze Aktion wagen. Ich schreibe euch hier nun mal den ganzen Code rein (mit ?Oncreate?,usw) und erkläre euch dann, was das alles zu Bedeuten hat:


Delphi-Quellcode:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,OpenGl;

type
TForm1 = class(TForm)
private
{ Private-Deklarationen } 
myDC : HDC;
myRC : HGLRC;
myPalette : HPALETTE;
procedure SetupPixelFormat;
public
{ Public-Deklarationen } 
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.SetupPixelFormat;
begin

end;

procedure Render;
begin

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
form1.myDC:= GetDC(Handle);
SetupPixelFormat;
myRC:= wglCreateContext(myDC);
wglMakeCurrent(myDC, myRC);
glEnable(GL_DEPTH_TEST);
glLoadIdentity;
end;

procedureTForm1.FormDestroy(Sender:TObject);
beginwglmakecurrent(0,0);
wgldeletecontext(mydc);
releasedc(handle,mydc);
end;

procedure TForm1.FormResize(Sender: TObject);
begin
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, Width/Height, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
end;

end.
So und nun die Erklärung:

Ich denke, wir fangen mal mit ?OnCreate? an:

Also: ?DC? bedeutet soviel wie Device Context... womit dann auch klar wäre, das in der ersten Zeile von ?oncreate? zunächt erst mal der Device ? Context unseres Hautfensters ausgelesen wird (wer nicht weiß, was das bedeutet: es ist nicht wirklich notwendig das zu wissen... wer noch nicht ewig mit PCs arbeitet muss es auch nicht wissen... die, die schon länger damit arbeiten wissen, was gemeint ist ? ich kann es nämlich nicht wirklich gut erklären)
In der nächsten Zeile wird dann unsere Prozedur ?SetupPixelFormat? auf... was die bedeutet, wisst ihr ja bereits: Dort werden wir einige kleine Settings vornehmen.
So... weiter im Kontext (im wahrsten sinne des Wortes):
Die nächsten beiden Zeilen bewirken zunächst, das aus dem Device Context unseres Fensters ein Open Gl Rendering Context (rc) erzeugt wird und daraufhin aktiviert wird.
Die nächste Zeile dürfte dagegen an sich klar sein: Hier aktivieren wir via ?glenable? den Open Gl Tiefentest. Dies bewirkt, das Open Gl immer überprüft, wo in der Tiefe das zu Zeichnende Objekt liegt... ist es zu weit weg, oder von etwas anderem verdeckt, wird es gar nicht erst berechnet. Insbesondere bei großen Szenen ist diese Tiefenüberprüfung also mehr oder weniger maßgeblich für die Performance der Szene... Open Gl erzwingt diesen Modus aber nicht (wäre auch schlecht... es gibt auch Situationen, wo der Tiefentest deaktiviert werden muss... z.B. wenn man mit viel Transparenz arbeitet)
Der letzte Befehl ist nicht ganz einfach zu erklären. Dazu muss man über die >Funktionsweise von Open Gl näher bescheid wissen. Und zwar: alle Objekte in Open Gl würden, wenn sie denken könnten und wüssten, wie sie entstehen praktisch wahnsinnig werden: Alle Objekte werden Praktisch über die sogenannte ?Welt-Matrix? (die dem aus dem Film Matrix nicht unähnlich ist) zunächst erstellt, dann gedreht, skaliert und natürlich auch verschoben. Dazu gibt es in Open Gl praktisch einen imaginären Punkt, welcher sagt, an welcher Stelle nun gezeichnet werden soll (besser: um welchen Punkt rum zu gezeichnet werden soll) ?glloadidentity? lädt nun den Ursprung (0,0,0) als diesen Punkt, oder auch gesagt: Es setz die ganze zukünftige Szene zurück. Dies ist zwingend notwendig, denn wir wollen unsere Szene ja nicht irgendwo ins Nirwana zeichnen, sondern wir wollen wissen, wo die Szene ist, damit wir uns diese ansehen können.
Im übrigen: es gibt nicht nur diese eine World ? Matrix, sondern es gibt noch viele mehr: eine für Texturen, eine für die Projektionseigenschaften, usw.

So... nachdem wir diesen Textbrocken von onCreate hinter uns gelassen haben, machen wir mal was kleineres: wir beschrieben onDestroy:

Denn an sich gibt es da nichts zu erklären: alle drei Prozeduren dienen nur dazu, den Rendering ? Kontext wieder frei zu geben, um Open Gl klar zu machen, dass es nun nicht mehr auf unserem Formular zeichnen soll.

Hmm... nun fehlt natürlich nur noch onresize...
Wie ihr vielleicht wisst, wird onresize aufgerufen, wenn die Größe des Formular geändert wird. An diesem Punkt muss man Open Gl quasi neu konfigurieren, damit nicht alle Objekte unserer Szene total verzerrt gezeichnet werden (ihr könnt ja mal Testweise diesen Code weglassen... ihr dürftet aber kaum glücklich damit werden)
An sich sind die Prozeduren hier sehr einfach zu verstehen:
Zunächst wird Open Gl klar gemacht, wie die neuen Maße unseres Fensters aussehen... besser: Wir legen den rechteckigen Rahmen fest, in dem gezeichnet werden soll. Dann schalten wir in die Projektionsmatrix damit wir die Darstellungsweise unserer Szene direkt verändern können. Nun setzen wir per glloadidenity diese Matrix komplett zurück (man erinnert sich ) Als nächstes setzen wir die neuen Settings für die Darstellung vor... das übernimmt für uns ?gluperspective?, welches 4 Parameter erwartet:
Der erste (bei uns 45) steht für die Gradzahl des Blickwinkels. Hier werden meistens werte zwischen 30 und 45 gewählt, die dem natürlichen Blickwinkel entsprechen. Der nächste steht für das Breiten ? Längen ? Verhältnis, welches dadurch angegeben wird, dass man die Breite durch die Höhe teilt. Die letzen zwei Parameter stehen für den nächsten und den entferntesten sichtbaren Punkt für unsere Kamera. Das heißt: wenn wir auf dem Ursprung steht, und in die z-Richtung sieht, dann ist der nächste Punkt, den man sehen kann einer mit der Z-Koordinate 1 und der entfernteste (der Horizont) wir durch Objekte mit der Z-Koordinate 100 gebildet.
Die letzen beiden Funktionen schalten an sich nur noch in den Normalmodus zurück, damit auch wieder normal gezeichnet werden kann.

Im übrigen: In dieser Initialisierung verwenden wir die perspektivische Darstellungsweise verwendet, welche die Realitätsnahe ist. Als Alternative gibt es noch die Orthographische, welche hauptsächlich in CAD ? Programmen verwendet wird. Allerdings werden hier alle Objekte mit ihrer Originalgröße dargestellt... unabhängig vor ihrer Entfernung zum Betrachter.


So... das war nun aber derbe viel. Ich hoffe, dass alle anderen Teile nicht ganz so theorieastig werden. Aber eine Sache fehlt noch: ?SetupPixelFormat? ist noch sehr mager mit Code bestückt. Wie bereits gesagt: in dieser Prozedur nehmen wir die Einstellungen für Open Gl vor. Ich poste hier einfach mal eine gültige Variante. Ich werde dieses nun nicht ganz so genau erklären, aber ich habe das Wichtigste mit Kommentaren versehen, damit ihr bei bedarf Änderungen problemlos vornehmen könnt (es wäre etwas arg viel, ins Detail einzugehen)

Delphi-Quellcode:
procedure TForm1.SetupPixelFormat;
var hHeap: THandle;
nColors, i: Integer; //Anzahl der Farben
lpPalette : PLogPalette; //Die Farbpalette
byRedMask, byGreenMask, byBlueMask: Byte; //Blau, Grün und Rot
nPixelFormat: Integer;
pfd: TPixelFormatDescriptor; //Dies ist der "Descriptor"... in ihm werden die Infos
// zwischengespeiichert

begin
FillChar(pfd, SizeOf(pfd), 0);
with pfd do
begin //wir woollen das Format bearbeiten
nSize := sizeof(pfd); // Länge der pfd-Struktur
nVersion := 1; // Version
dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or
PFD_DOUBLEBUFFER; // Flags
iPixelType:= PFD_TYPE_RGBA; // RGBA Pixel Type
cColorBits:= 24; // 24-bit color (Anzahl der Farben)
cDepthBits:= 32; // 32-bit depth buffer
iLayerType:= PFD_MAIN_PLANE; // Layer Type
end;
nPixelFormat:= ChoosePixelFormat(myDC, @pfd); //Das Pixel-Format
SetPixelFormat(myDC, nPixelFormat, @pfd); // wird übertragen

// Farbpalettenoptimierung wenn erforderlich

DescribePixelFormat(myDC, nPixelFormat, //alles ab hier ist zwecks einstellungen nicht
//mehr wichtig, sondern schlicht und einfach nur noch notwendig... ;-)
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 := (((i shr 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;
Nun ist es an sich fast vollbracht. Uns fehlen nur noch 2 Dinge: Einen Platz, wo wir ein Objekt rendern können und ein Objekt.
Um ersteres werden wir uns nun noch kümmer:
Legt (direkt unter SetupPixelFormat)ne Prozedur ?Render? an, welche nur drei Befehle beinhalten sollte:

Delphi-Quellcode:
Prozedure render;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;

SwapBuffers(form1.myDC);
end;
Der erste Befehl bewirkt, dass unsere ganze Szene, welcher sich noch im Puffer befindet, gelöscht wird, damit es nicht zu Überschneidungen und Verschmierungen kommt. Wer mal sehen will, was es heißt, diesen Befehl nicht auszuführen, der sollte mal ne Runde CS zocken und dann als Spectator durch eine Wand laufen... alles verwischt und verschmiert total.
Der zweite Befehl sollte schon bekannt sein: er setzt die World ? Matrix wieder zurück, damit die Szene auch wieder am richtigen Ort mit richtiger Rotation und Skalierungen gezeichnet wird. Der letzte Befehl bewirkt nun noch, das Open Gl die Szene auch wirklich darstellt.

Nun müssen wir nur noch die Render ? Prozedur irgendwie aufrufen. Unter der VCL bietet sich dafür der Timer an. Wir erstellen nun also einen normalen Timer, dessen Intervall wir auf 1 einstellen und lasen diesen unsere Render ? Prozedur aufrufen.

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
render;
end;
Wenn ihr die Delphi X ? Komponenten habt, solltet ihr den DX ? Timer verwenden. Dies hat folgende Gründe:
Wenn ihr den normalen Timer auf eins stellt, schafft er dennoch nichts schnelleres, als etwa 50. Das bedeutet, dass wir maximal 20 fps erreichen können. Der DX ? Timer hingegen ist viel korrekter. Mit ihm erreicht man normalerweise ein Maximum von ca. 80 ? 160 FPS.
Diese schon recht dollen FPS ? Zahlen wird man zwar insbesondere mit großen szenen fast nie erreichen, aber man schafft fast immer mehr, als mit dem normalen Timer.

So... nun haben wir Open Gl schon beinahe komplett lauffähig. Nun fehlt nur noch unseres Objekt... aber das behandeln wir im nächsten Kapitel. Ich hoffe, dieses Kapitel hat euch nicht entmutigt, denn die Programmierung von 3d ? Szenen mit Open Gl ist sehr einfach... bloß die Initialisierung ist eine etwas umfangreiche und harkeilige Sache.
Wer in diesem Kapitel nicht mitgekommen ist, den kann ich beruhigen: das nächste wird viel einfacher. Wenn ihr wollt, könnt ihr euch auch einfach die ganze Initialisierung saugen... auf der Indexseite zu diesem Kurs gibts alle Samples...








------------ Teil 3 ----------

Open Gl - Delphi ? Kurs Teil 3: Objekte und die World Matrix

Einleitung

*Mit den Fingern Knack* so... nun ist es also schon wieder soweit: der dritte Teil meines Delphi ? Open Gl ? Kurses steht an. Diesmal (Mitlehrerweile schon 4 Wochen nach dem ersten Teil) wollen wir endlich mal was zeichnen! Ich hoffe, dieser Teil wird nicht ganz so Theorielastig, wie der Letzte. Aber ich kann euch beruhigen: wahrscheinlich wird dieser Teil ein großer Spaß... auch wenn ich leider doch mit ein wenig Theorie anfangen muss, aber wenigstens dürfte diesmal am ende wenigstens was zu sehen sein (wenn man das Sample des letzen Teiles startet, hat man noch einen schwarzen Bildschirm). Also los!

Die Open Gl Basics

So Leute nun wird es Zeit, euch über die Basics von Open Gl aufzuklären. Also wie gesagt: Wenn ihr bislang eure Szene startet, so werdet ihr bemerken, dass es sich nur um einen schwarzen Bildschirm handelt. In diesen wollen wir nun was ?reinrendern?. Bloß wohin genau? Gibt es irgendwelche Koordinaten?
Ja, es gibt welche! Es handelt sich dabei um die Koordinaten der World Matrix oder auch Welt Koordinaten. Viele von euch haben ja schon mal in Mathe ein Koordinatensystem gesehen, und unseres ist diesem nicht unähnlich. In der Mitte des Ganzen ist der Ursprung, also der Punkt, bei welchem alle Koordinaten den wert null haben. Neben der X ? Achse, welche links negativ ist und rechts positiv, und der Y ? Achse, die unten negativ und oben positiv ist, gibt es in Open Gl auch noch die Z ? Achse. Die verläuft aber nicht, wie viele denken, von hinten positiv nach vorne negativ, sondern sie wird nach hinten hin negativ!!! Dies ist insbesondere für Direkt X ? Freaks sehr schwer am Anfang, da es dort genau anders herum ist. Man sollte also darauf aufpassen, wenn man sich keine riesigen Fehler einfangen will. Ich habe dazu mal eine Kleine Grafik gemalt:

@alle, die dieses Tut auf der Delphipraxis-Site lesen: hier war im Original ein Bild

So... das hätten wir schon mal. Aber wo genau sind wir nun? Tja, das ist leicht beantwortet: wir stehen dort, wo alles begann ? auf dem Ursprung. Und was können wir alles sehen? Das hatten wir im letzen Kapitel doch schon mal: alles, was nicht weiter als 100 Einheiten von uns weg ist und nicht gerade außerhalb unseres 45° Winkels liegt... also eine Ganze Menge. Aber wir müssen eines Beachten: dank unserer Einstellungen darf das Objekt nicht näher als 1 sein, sonst sehen wir gar nichts!!!

Ich will was Zeichnen!!!

Ja ja kommt ja schon...
Also, wie malt man denn nun überhaupt was?
Auch da gibt es 2 wichtige Basics:
1) Alle Objekte werden zwischen glbegin( ) und glend; gerendert. In der Klammer von glbegin gibt man dazu den Objekttyp an. Z.B. ob es sich um Punkte, Linien, Dreiecke oder Quadrate handeln soll.
2) Alle Objekte werden durch Punkte gezeichnet. Der befehl für einen Punkt heißt glvertex. Glvertex kann aber verschieden viele Parameter haben. So gibt es eine Variante glvertex2f und eine glvertex3f. Der Unterschied ist klar: glvertex2f verlangt 2 Floats als Parameter (x und y Koordinate)... glvertex3f hingegen 3 (x, y und z Koordianten)
Und was sagt uns das? Tja... man kann mit Open Gl nicht nur 3d, sondern auch 2d zeichnen, was aber nicht unbedingt Sinn der Sache ist. Ich habe mir überlegt, dass wir folgende Szene erreichen wollen:


@alle, die dieses Tut auf der Delphipraxis-Site lesen: hier war im Original ein Bild


Was brauchen wir denn zunächst dazu? An sich benötigen wir zunächst mal ein Quadrat. Und wie zeichnen wir das? Wie oben bereits gesagt mit 4 Punkten. Wir haben ja bereits unsere Render ? Prozedur. In dieser habe ich beabsichtigt eine keine Lücke gelassen. In diese kommt nun unserer Code. Wir wollen mal sehen, was passiert, wenn wird diesen dort eintippen:

Delphi-Quellcode:
Glbegin(gl_quads); //wir wollen ein Viereck zeichnen
glVertex3f( 1 , 1, -2);
glVertex3f( -1 , 1, -2);
glVertex3f( -1 , -1, -2);
glVertex3f( 1 , -1, -2);
glend;
So, das will ich erst mal erläutern:
Also mit glbegin(gl_quads); beginnen wir, Vierecke zu zeichnen. Danach folgen die Vier Eckpunkte und zuletzt das Abschleißende glend. Aber was ist das, wenn wir das nun starten? Die Szene ist urplötzlich ganz weiß!!! Wie kann das denn nun? Die Erklärung für dieses Phänomen ist sehr einfach: Der nächste Punkt, den wir sehen können, hat die Koordinaten (0,0,-1) das heißt: wir sind sehr nahe drauf auf unserer Kamera! Unser Objekt ist schlich zu nahe, um ins Bild zu passen! Was tun wir folglich dagegen? Wir zeichnen es etwas weiter weg. Mit diesem Code zeichnet man es z.b. schon mal 4 Einheiten weiter nach hinten, als bisher. Das hilft schon sehr.

Delphi-Quellcode:
Glbegin(gl_quads); //wir wollen ein Viereck zeichnen
glVertex3f( 1 , 1, -6);
glVertex3f( -1 , 1, -6);
glVertex3f( -1 , -1, -6);
glVertex3f( 1 , -1, -6);
glend;
Das sieht dann schon eher, wie das gewünschte Viereck aus:

@alle, die dieses Tut auf der Delphipraxis-Site lesen: hier war im Original ein Bild

Aber irgendwie sieht das noch sehr eintönig aus. Aber das ändern wir nun.


Ich sehe... Farben

So... wie bekommen wir nun also etwas Farbe in unseres Viereck? Also, falls nun schon irgendwer auf den Gedanken gekommen ist, jedes Pixel für Pixel einfach nachzuzeichnen, wird er gelyncht! Das geht viel einfacher! Man ist es ja bereits gewohnt, das sich Farbe in PCs aus rot, grün und blau zusammensetzt. Und so läuft das auch hier! Mit dem Befehl glcolor3f, welcher drei Parameter verlangt (sieht an ja auch an dem ?3f?) kann man nun eine Farbe setzen. Aber es gibt eines zu beachten: Die Farbwerte werden zwischen 0 und 1, also als Float angegeben! Wer nun also gerne seine HTML ? Farben verwenden wollte, der sollte alle Farbwerte schleunigst durch 256 teilen, damit das auch hinhaut! Also: wir schreiben nun vor dem Zeichnen unseres Vierecks ein glcolor3f, mit dem wir eine rote Farbe erzeugen wollen:

Delphi-Quellcode:
glcolor3f(1,0,0) //rote Farbe
Glbegin(gl_quads); //wir wollen ein Viereck zeichnen
glVertex3f( 1 , 1, -6);
glVertex3f( -1 , 1, -6);
glVertex3f( -1 , -1, -6);
glVertex3f( 1 , -1, -6);
glend;
Dann sieht das Ganze schon mal so aus:

@alle, die dieses Tut auf der Delphipraxis-Site lesen: hier war im Original ein Bild

Aber wo bekommen wir nun diese schönen Farbverläufe her? Das ist an sich ganz einfach:
Man kann für jeden Punkt eine einzelne Farbe angeben. Da ja alle punkte dank unseres glbegin(gl_quads) zu einem Viereck verbunden wird, werden die Farbverläufe einfach automatisch berechnet! Dies kann manchmal sehr nützlich sein. Daher brauchen wir unseren Quadratcode nur so umschreiben:
Glbegin(gl_quads); //wir wollen ein Viereck zeichnen glcolor3f(1,0,0) //rote Farbe glVertex3f( 1 , 1, -6); glcolor3f(0,1,0) //grüne Farbe glVertex3f( -1 , 1, -6); glcolor3f(1,1,0) //gelbe Farbe glVertex3f( -1 , -1, -6); glcolor3f(0,0,1) //blaue Farbe glVertex3f( 1 , -1, -6);glend;
Und schon haben wir unseren Farbverlauf!


Vom Schieben, Drehen und Skalieren

An sich ist Open Gl ja richtig brutal und kriminell!
Hier werden einige Autos und andere Objekte durch die Gegend geschoben, woanders werden Dinge komplett verdreht und irgendwo skaliert man aus einer Mücke einen Elefanten! Einfach kriminell!
Aber so schlimm ist es nun auch wieder nicht. Was wäre das für eine Welt, ohne Animationen? Wäre nicht gerade lustig, würde ich sagen... Na ja, was soll also das Geschwafel? Ich möchte euch nun beibringen, wie das eben genannte also funktioniert.
Ich fange mit dem Verschieben an:

Zum Verschieben reicht in Open Gl ein einziger Befehl! Nämlich gltranslate. Dieser Befehl verlangt - wie sollte es auch anders - 3 Parameter. Diese sagen ganz easy aus, wohin verschoben werden soll. Wenn ich also vor unserem Viereck ?gltranslate(0,1,-2)? aufrufe, dann verschieben wir es um ca. zwei Weltkoordinaten nach hinten und um eine nach oben. Das heißt also auch, dass wir unser viel zu nahes Anfangsquadrat hätten lassen können und einfach ?gltranslate(0,0,-4)? davor hätten aufrufen können, womit ich euch aber erst nicht belasten wollte. Nun werde ich erst mal zum drehen kommen (keine Sorge, ich mache noch ein Sample am Ende mit allen befehlen zusammen... versprochen)

Es dreht sich

Das Drehen geht an sich genauso einfach von der Hand, wie das Verschieben. Zum Drehen braucht man nämlich nur den Befehl ?glrotate?. Dieser Befehl verlangt insgesamt 4 Parameter. Der erste ist der Winkel in Grad. Die andren Drei stehen wieder für eine X,Y und Z ? Koordinate, welche die Achse beschrieben soll, um die rotiert wird. Wenn man also ?glrotate(45, 0, 1, 0)? aufruft, dann dreht sich alles nachfolgende um 45° um die Y ? Achse.
Was man nun zuerst tut (Drehen oder Verschieben) ist jedem selber überlassen, aber es hat sehr verschiedene Auswirkungen! Das liegt daher, das immer um den Punkt gedreht wird, um den eben ?translatet? wurde! Spielt doch einfach etwas damit (und mit den Parametern) rum. Ich werdet den Bogen schnell raushaben!

Na denn: Skalieren

So, womit wir auch schon beim skalieren wären. Lasst es uns kurz machen: zum Skalieren braucht man nur den Befehl ?glscale?, der insgesamt drei Parameterchen haben möchte. Die erste gibt die Skalierung der X ? Richtung an, womit auch klar wäre, das die beiden anderen für Y und Z zuständig sind. Wenn man nun also ein Objekt gleichmäßig vergrößern oder verkleinern will, so muss man einfach alle Werte gleichmäßig erhöhen oder erniedrigen. Eine Sache muss aber noch beachtet werden: es handelt sich bei den werten um Multiplikatoren und nicht um Summanden!!! Einige Leute denken: ?Wenn du null als Parameter angibt, dann verändert sich Größe null? und wundern sich dann, wenn urplötzlich nichts mehr zu sehen ist. Also: wenn ihr die Größe eine Koordinate nicht ändern wollt, dann solltet ihr 1 angeben, wollt ihr sie verdoppelt, so gebet 2 an und wollt ihr sie halbieren, so hat der Parameter 0.5 zu heißen! Ach ja noch was: Ein Objekt wird immer vom Ursprung aus skaliert. Damit macht es dann doch einen Unterschied, ob wir ein Objekt gleich an die richtige stelle schieben, oder aber sie am Ursprung erstellt und dann verschiebt.....

Und nun: Das Sample

So, nun möchte ich also mit euch ein kleines Sample bauen.
Das ganze soll so aussehen:
Wir verwenden unseres Quadrat von vorhin und versuchen, dieses
1) von der Größe her pulsieren zu lassen
2) langsam immer von oben nach unten zu bewegen
3) es ständig um die eigene Z ? Achse rotieren so lassen

Damit wäre unser Auftrag klar. Zunächst benötigen wir insgesamt fünf neue globale Variablen:

Delphi-Quellcode:
var Form1: TForm1;
scale : single = 1; //Für die Skalierung
rotation : integer = 0; //Zahl in °, um die gedreht wird
move : single = 0; //Größe der Bewegung
scaledir : boolean; //Richtung der Skalierung (größer / kleiner)
movedir : boolean; //Richtung der Bewegung (rauf / runter)
So... damit hätten wir schon mal die wichtigsten Variablen beisammen. Nun müssen wir diesen nur noch werte zuweisen. Dazu habe ich mir gedacht, nehmen wir uns einen neuen Timer, den wir auf etwa 50 stellen. Dort müssen wir dann die werte zuweisen:

Delphi-Quellcode:
procedure TForm1.Timer2Timer(Sender: TObject);
begin
if scale > 1.2 then //ist dei höchste stufe der Skalierung erreicht?
begin
scaledir := false; //Ja : Skalierung umkehren
end;

if scale < 0.8 then //ist dei niedrigste Stufe der Skalierung erreicht?
begin
scaledir := true; //Ja : Skalierung umkehren
end;

if scaledir = true then //Soll die scalierung größer werden?
begin
scale := scale + 0.02; //JA: Scale erhöhen
end
else
begin
scale := scale - 0.02; //Nein: Scale ernidrigen
end;

inc(rotation); //Die rotation in "°" erhöhen

if move > 1 then //ist der höchste Punkt der Bewegung erreicht?
begin
movedir := false; //Ja : Bewegung umkehren
end;

if move < -1 then //ist der niedrigste Punkt der Bewegung erreicht?
begin
movedir := true; //Ja : Bewegung umkehren
end;

if movedir = true then //Soll die Bewegung nach oben gehn?
begin
move := move + 0.02; //JA: Move erhöhen
end
else
begin
move := move - 0.02; //Nein: Move ernidrigen
end;

end;

Ich denke mal, dass ich diesen Quelltext nicht unbedingt näher erklären muss. Er erklärt sich ja praktisch von selbst: zunächst wird die Skalierung, dann die Rotation und zuletzt die Bewegung bearbeitet. Wenn man das ganze nun aber startet, dann sieht man nichts! Besser: es bewegt sich nichts! Das ist aber auch nicht schwer zu erraten, wieso. Ganz einfach: wir verarbeiten die neuen Werte noch nicht. Dazu müssen wir noch unsere Render ? Prozedur noch etwas abändern:

Delphi-Quellcode:
procedure render;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;


gltranslate(0,move,0); //wir bewegen alles etwas nach oben oder unten
glscale(scale,scale,1); //Nun skalieren wir die Szene
glrotate(rotation,0,0,1); //Und ab in die Drehung um die Z-Achse ;-)


glBegin(GL_Quads);
  glcolor3f(1,0,0);
  glVertex3f( 1 , 1, -6);
  glcolor3f(0,1,0);
  glVertex3f( -1 , 1, -6);
  glcolor3f(1,1,0);
  glVertex3f( -1 , -1, -6);
  glcolor3f(0,0,1);
  glVertex3f( 1 , -1, -6);
glEnd();
gltranslate(0,0,-3);
glcolor3f(0,0,1);

SwapBuffers(form1.myDC);
end;
Das wäre auch schon alles! Wenn wir nun das ganze starten dürften wir ein quietschbuntes Viereck sehen, welches gegen jedes Gesetz der Physik verstößt. Aber das ist an sich ja halb so schlimm: es war ja quasi Sinn der Sache, euch mal irgendwie alles zusammen zu zeigen. Wer dort noch nicht ganz durchgestiegen ist: saugt euch das Sample und spielt etwas mit den Parametern rum: ihr werdet dabei ne Menge lernen!

Nachwort

So, das war?s auch ?schon? mit Teil 3 meines Open Gl Kurses. Ich hoffe, diese Acht Seiten waren etwas Unterhaltsamer, als die sieben Seiten aus dem 2. Teil und ich hoffe, dass ich euch in zwei Wochen wieder begrüßen darf, wenn wir zum Thema ?Zeichenmethoden? kommen. Dort werde ich euch beibringen, wie man Punkte, Linien, Dreiecke, Rechtecke und Polygone in den verschiedensten Zeichenstärken, usw. Macht. Zudem machen wir noch einen kleinen Abstecher in die Welt der 3d ? Objekte (in der wir ab dann auch bleiben werden). Ich werde euch also zeigen, wie man Pyramiden, Würfel und Kugeln auf den Screen bekommt. Ich hoffe, wir sehen uns wieder.








------------ Weiteres ----------

Der Kurs geht natürlich weiter, das Problem ist blos, dass es von noch nicht allen Teilen online-Versionen gibt und ich damit von noch nicht allen alle Bilder hochgeladen habe...
Leider arbeite ich in fast allen Kursteilen ab Teil 4 mit sehr vielen Bildern und deshalb wären diese Parts recht unverständlich ohne...
Naja, damit ihr wisst, was euch erwartet hier ne Liste alle Teile:

Teil 1: Was ist Open Gl
Teil 2: Open GL Initialisieren
Teil 3: Das erste Objekt und die World Matrix
Teil 4: Zeichenmethoden
Teil 5: Texturen
Teil 6: Blending
Teil 7: Lichter mit Blending
Teil 8: Kamerabewegung

Und hier der Direktlink zur Kurs-Seite:
http://www.dcw-group.net/index.php?m.../oglkurs/index

Und damit ihr mir auch glaubt, dass sich das ganze Lohnt, gibts hier noch n kleines Bild (Teil 8):

EDIT SAKURA: Schade nur, dass das Bild durch Username/Passwort zugriffsgeschützt ist und wir es nicht sehen können

Cu
Mr_T

[edit=sakura] Link auf geschütztes Bild entfernt. Mfg, sakura[/edit]
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!
 
Benutzerbild von gordon freeman
gordon freeman

 
Delphi 2005 Personal
 
#21
  Alt 18. Apr 2005, 12:40
Ist eigentlich standardmäßig bei Delphi dabei. Einfach die Unit OpenGl einbinden:
uses {...}, opengl;
Martin
  Mit Zitat antworten Zitat
RedDust

 
Delphi 2005 Personal
 
#22
  Alt 18. Apr 2005, 13:31
THX Leuz
Mario Franze
  Mit Zitat antworten Zitat
Benutzerbild von Airblader
Airblader
 
#23
  Alt 18. Apr 2005, 13:32
Zitat von gordon freeman:
Ist eigentlich standardmäßig bei Delphi dabei. Einfach die Unit OpenGl einbinden:
uses {...}, opengl;
Und bei bestimmten Dingen werden dann halt GLaux.pas und GLaux.dll benötigt, die waren bei mir nich standardmäßig dabei =)
Ingo Bürk
  Mit Zitat antworten Zitat
RedDust

 
Delphi 2005 Personal
 
#24
  Alt 18. Apr 2005, 13:37
Wo kann man denn die Dateien finen Airblader?
Mario Franze
  Mit Zitat antworten Zitat
Benutzerbild von Airblader
Airblader
 
#25
  Alt 18. Apr 2005, 14:01
Zitat von Airblader:
Zitat von RedDust:
Hab' mir das Tut durchgelesen, leider fehlt mir die OpenGL Komponente, könnt ihr mir verraten wo ich diese finde?
Bei Google suchenOpenGl.pas
Bei Google suchenGLAux.dll
Bei Google suchenGLaux.pas
oder hier:
DelphiGL
Wer lesen kann ist klar im Vorteil
Ingo Bürk
  Mit Zitat antworten Zitat
Benutzerbild von Mr_T
Mr_T

 
Delphi 2005 Personal
 
#26
  Alt 21. Apr 2005, 13:19
Ich verstehe die Frage nach einer OpenGl-Komponente irgendwie nicht wirklich, da auf echt jedem Rechner eine OpenGl32.dll vorhanden ist (wobei die von Microsoft echt Käse ist) und man halt über die opengl.pas (viel besser über die dglopengl.pas) zugreift ... alos nichts Komponente ^^
Allerdings sei dazu gesagt, dass ich den Kurs nach dem Abi nochmal neu aufziehen werde ... es ahben sich seit 2002 (qals die ersten Sätzte entstzanden) zu viel geändert ... es gibt neue OpenGl-Versionen (1.5), Shader gibts nun auch und auch und irgendwie gibts elegantere Lösungen zum Texturenladen als Glaux ^^
Ach ja .. Delphi 4 / 5 - Zeiten ahben wir auch net mehr ... muss mal was für Delphi 2005 tun ^^ Naja, mal gucken ... erstmal in n paar Wochen Abi bestehen ^^
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 07:50 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