Welcome to the new Friends-of-FPC!

Here you can find all kinds of information about the FreePascal Compiler. We have many tutorials and howtos as well as a selection of tools to help you with your programming. We also have some example codes for you. And if you want to contribute some information/ sources/ tools yourself you can do so.
Also we have finally relaunched the FoFPC forum. It's your chance for some Q&A about everything FreePascal.

Friends-of-FPC

Tutorials: Learn how to code with FreePascal.

Source Codes: A collection of examples, miscellaneous source codes and open source stuff.

Tools and Help Files: Intro- duction of some tools that might help you with FPC.

Community

Forum: Ask or answer questions about the FreePascal Compiler, programming or just babble about coding.

Contribute! Contribute your own Tutorial, Source Codes or Tools and send them to us!

Website

About: Information about Friends-of-FPC.org.

Einführung in OpenGL - Teil 8 - by Delax

Diesmal geht es um Depth Functions. Wer mal eben schnell übersetzt kommt auf "Tiefenfunktionen". Dicht dran. Hier ein Beispiel worum es geht.

Nehmen wir einmal an, wir erzeugen zwei Dreiecke hintereinander und rotieren dann die Matrix. Einfache Sache, da sind also 2 Dreiecke, die um den Mittelpunkt rotieren. Hier ein Beispiel:

  glClear( GL_COLOR_BUFFER_BIT );
  glLoadIdentity();

  glRotatef( rotation, 0.0, 1.0, 0.0 );                         

  glBegin( GL_TRIANGLES );

    glColor3f(1.0, 0.0, 0.0);  

    glVertex3f(0.0, 1.0, 0.0);
    glVertex3f(-1.0, -1.0, 0.0);
    glVertex3f(1.0, -1.0, 0.0);

    glColor3f(0.0, 1.0, 0.0);  

    glVertex3f(0.0, 1.0, 1.0);
    glVertex3f(-1.0, -1.0, 1.0);
    glVertex3f(1.0, -1.0, 1.0);

  glEnd();  

Wenn ihr das kleine Beispiel herunterladet, kompiliert und anschaut seht ihr etwas seltsames. Das grüne Dreieck will einfach nicht hinter das rote, obwohl es sich eigentlich hinter dem roten befindet.

Nur weil ein Objekt hinter dem anderen ist heißt das für OpenGL nicht automatisch das es auch dahinter gezeichnet werden muß. OpenGL zeichnet von sich aus immer die Flächen von hinten nach vorne. Also eine Fläche, die zuerst gezeichnet wird ist für OpenGL erst einmal hinter der nächsten Fläche. Deshalb ist das grüne Dreieck auch immer vor dem roten.

Jetzt hat man ein paar Möglichkeiten alles "richtig" darzustellen. Man kann die ganzen Flächen selbst ordnen und dafür sorgen das alle Flächen, die näher am Betrachter sind einfach später gezeichnet werden. Oder man verwendet Buffer, die für jeden Pixel einen Z-Wert haben. Wenn nun ein neuer Wert kommt (weil zum Beispiel ein neues Dreieck gezeichnet werden soll) wird der Wert überprüft und wenn der neue Wert vor dem aktuellen liegt, wird auch nur der aktuelle gezeichnet. Genau diese Vorgehensweise wollen wir nutzen.

Um die Depth Functions zu aktivieren genügt ein simples glEnable. Zusätzlich müssen wir natürlich noch angeben was wir gerne für Funktionen hätten und wie diese beschaffen sein sollen. Hier die zusätzlichen Zeilen aus der OpenGL_Init Prozedur.

  glClearDepth( 1.0);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);

Die erste Zeile setzt den Wert fest, auf den der Buffer zurück gesetzt werden soll. Stellt euch das ganze einfach als glClearColor vor, nur eben für den Depth Buffer. Mit glEnable(GL_DEPTH_TEST); aktivieren wir das angesprochene Depth Testing.

Als Tiefenfunktion wählen wir glDepthFunc(GL_LEQUAL);. GL_LEQUAL bedeutet das alles was niedriger oder gleich dem aktuellen Wert ist gezeichnet wird. "Wie niedriger? Ich dachte höher!" denkt ihr euch vielleicht. Schon klar, aber die Werte für die Buffer werden mit 1/Z-Wert berechnet. Also ist ein Z-Wert von 2 kleiner als der von 1, obwohl er näher zum Betrachter liegt, da 1/1 = 1 und 1/2 = 0.5. Bei GL_LEQUAL wird also letzteres gezeichnet. Bei GL_GREATER würde als Beispiel ersteres gezeichnet.

Jetzt kommen wir auch noch einmal zu glClearDepth. Der hier eingetragene Wert reicht von 0.0 bis 1.0. Das ist der Wert, auf den jeder Pixel wieder zurück gesetzt wird. Wenn wir den Wert auf 1.0 setzen und mit GL_LEQUAL arbeiten ist jeder gesetzte Pixel kleiner oder gleich als 1. Setzt man den Wert des Löschens auf 0.0 und arbeitet mit GL_LEQUAL wird man gar nichts mehr sehen. Wieso? Nun, wenn der Wert auf 0.0 zurück gesetzt wird, wie soll es da noch kleiner werden? In dem Fall würde man mit GL_GREATER arbeiten, aber hoppla, dann ist die Reihenfolge der Flächen vertauscht und was weiter weg ist, wird vor dem näheren erscheinen.

Junge, junge. Gar nicht so leicht, was? Und dabei hab ich mich bemüht das ganze so einfach wie möglich zu erklären (wie immer: das "Biegen der Realität" ist bei so Erklärungen immer erlaubt, um es nicht zu kompliziert zu machen ;). Wie auch immer, die anderen Möglichkeiten Flächen zu ordnen erspare ich euch. Wir machen hier simples OpenGL und wichtig ist nur: Mit glClearDepth(1.0) und glDepthFunc(GL_LEQUAL); liegt ihr eigentlich in 95% der Fälle goldrichtig. Das nur für alle, die sich nicht für die obrige Erklärung interessieren.

So, und eigentlich fehlt nur noch eine Erweiterung. OpenGL weiß nämlich noch gar nicht das es von nun an immer den Depth Buffer löschen soll. Also müssen wir unsere Zeile in Draw_OpenGL erweitern zu glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT); Und das war es auch schon. Hier das komplette Beispiel mit den oben genannten Änderungen. Wie ihr seht ist jetzt die Darstellung der Flächen korrekt.

Delax/ Sundancer Inc.
[delax@sundancerinc.de]

Back to previous page

Useful Links









Link to us