|
Antwort |
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:
So und nun die Erklärung:
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. 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:
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.
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; 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:
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.
Prozedure render;
begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity; SwapBuffers(form1.myDC); end; 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:
Wenn ihr die Delphi X ? Komponenten habt, solltet ihr den DX ? Timer verwenden. Dies hat folgende Gründe:
procedure TForm1.Timer1Timer(Sender: TObject);
begin render; end; 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:
So, das will ich erst mal erläutern:
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; 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:
Das sieht dann schon eher, wie das gewünschte Viereck aus:
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; @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:
Dann sieht das Ganze schon mal so aus:
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; @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:
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:
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)
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:
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!
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; 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! |
Delphi 7 Professional |
#11
Warum werden solche Wünsche, Anregungen, Kritiken den nicht an den Author bzw. der Seite gemeldet, damit man sowas vielleicht einmal in Angriff nehmen kann. Es gibt auch Authoren, die sich aus solchem Feedback etwas machen, auch wenn es viele nicht glauben...
Aber einmal im Ernst. Wo genau ist dein Problem? Ich denke bei einer aktuellen CAD-Anwendung will niemand mehr wirklich in den 2D-Bereich zurück verfallen. Sicherlich werden durch die dritte Dimension einige Dinge wie selektion ein kleines wenig komplizierter... Wenn Du einen kleinen Blick ins Redbook/Wiki/Manpages wirfst und Dir die orthogonale Projektionsmatrix ansiehst, die im 2D-Tutorial verwendet wird, wird die auffallen, dass man diese auch verwenden kann ohne dabei die gewohnten Pixelkoordinaten einzusetzen, sondern einfach um das 3D-Dimensionale aus der Szene zu nehmen (Sprich die Tiefe). Wenn Du dann so frech bist und definierst einen Inch als eine Weltkoordinate, sollte man auch ohne großes Umberechnen die Elemente abbilden können. Irgendwo bei uns im Forum gab es IMAO einmal jemanden der ein ähnliches Projekt im Angriff genommen hat. Keine Ahnung ob da etwas drauß geworden ist.
Florian Sievert
|
Zitat |
Delphi 12 Athens |
#12
Ah, einer der "Macher" - - ich denke dann ist das FeedBack, wenn auch über Umweg, ja doch angekommen!
Zu 2D/3D: Du hast schon Recht, wenn du sagst, dass bei aktuellen Anwendungen nicht wirklich jemand in den 2D Bereich zurückfallen will. Aber bedenke, dass es auch noch (Nischen-)Anwendungen gibt, die z.B. überhaupt kein 3D erfordern! Beispiel: Leiterplattendesign / Schaltplanentwurf! 3D nutzt hier i.d.R. nur etwas in der Visualisierung des Endproduktes (der Leiterplatte) zur optischen Kontrolle der Machbarkeit für den Designer. Das Problem ist im Moment, dass mir in OGL noch etwas die Basics fehlen. Es gibt zwar viele gute (und schlechte) Tut's zu 3D und auch 2D die einem bereits viel zeigen, aber ein Tut zur 2D Welt, welches sich nicht mit Spielen und Aninationen sondern mit einem "Produktiveinsatz" befasst hab ich noch nirgends gefunden. Ich bin dran, mich da Schritt für Schritt so langsam durchzuwuseln - auch wenn ich damit vielleicht das Rad zum 2ten mal erfinde und mich daher beim Erscheinen des Entwicklers im Oktober vielleicht totärgern werde. Natürlich hab ich hier bereits nach "Artverwandtem" gesucht, aber bislang leider noch nichts passendes gefunden. Mein Wunsch-Tut wäre ein kleines, einfaches 2D-OGL-Zeichenprogramm: Kreis, Linie, Recheck, Zoom, Grid, Load/Save/Print. Allerdings bin leider z.Zt. auch anderweitig etwas in Zeitnot, so dass ich das ganze noch um ca. 1-2 Wochen schieben muss. : |
Zitat |
FreePascal / Lazarus |
#14
So, ich hab mir jetzt mal den OGL-Kurs angesehen und ich muss sagen: Super
Aber in dieser Prozedur:
Delphi-Quellcode:
zeigt mir der Compiler an: Das Programm oder die Unit 'OpenGL' ruft sich selbst wieder auf.
procedure Render;
begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity; 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; SwapBuffers(form1.myDC); end; Was hab ich denn da falsch gemacht? Hab Delphi7 PE...
Julian J. Pracht
|
Zitat |
Delphi 2005 Personal |
#16
So, habe Mr_T gestern 'ne PN gesckickt, ahb aber leider noch keine Antwort bekommen. Aber vieleicht kennt sich ja einer von euch inzwischen so gut mit OpneGL aus, dass ihr mir helfen könnt.
Ich habe das Tut von Mr_T genau befolgt. Aller dings funktionieren folgende Prozedure bei mir nicht:
Ich mach das ganze mit Delphi4 auf 'nem WinXP-Rechner. Hatte jemand ein ähnliches Problem und kann mir helfen? tia, cu gordon
Martin
|
Zitat |
Delphi 2005 Personal |
#17
Hab gerade die PN von Mr_T erhalten. Mit den Befehlen:
funzt es!!
Martin
|
Zitat |
|
#18
Hi Leute!
Erst mal n fettes Lob für die ganzen Tutorials von Mr T !!! Die sind echt fätt! Hab aber doch noch ne kleine Frage - bezogen auf das Tutuorial 2 : Was muss ich bei der Initialisierung ändern, um das Programm im Vollbild-Modus laufen zu lassen ? Schon mal Danke im Voraus für die Hilfe! Tobi |
Zitat |
Delphi 2005 Personal |
#19
Hab' mir das Tut durchgelesen, leider fehlt mir die OpenGL Komponente, könnt ihr mir verraten wo ich diese finde?
Mario Franze
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
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 |
LinkBack URL |
About LinkBacks |