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 16 - by Delax

Eigentlich war geplant in diesem Teil "Spotlights" bzw. gerichtetes Licht durchzunehmen, aber ich dachte mir, ihr habt euch eine Abwechselung verdient ;) Deshalb geht es diesmal um Darstellungs-Listen oder auch Display Listen.

Diese Listen sind nicht nur hilfreich im Alltag, sie bringen auch Performance, sparen Speicher und kochen Kaffee. Doch was ist eine Display Liste? Nun, ganz einfach - es ist eine Abfolge von OpenGL Befehlen, die nach Bedarf aufgerufen werden.

Um das zu veranschaulichen bauen wir uns erst einmal eine neue Szene. Her mit einer Säule mit 4 Seiten, bestehend aus Fuß (4 Quads), Körper (4 Quads) und Kopf (4 Triangles). Macht insgesamt 12 Flächen bzw. 44 Vertices. Außerdem stellen wir die Flächen schön schräg, dass ihr euch an FindNormal() gewöhnen könnt ;)

  glBegin(GL_QUADS);
  glColor3f( 0.0, 0.0, 0.5 );

   glNormal3f(0.0,0.0,1.0);
    glVertex3f( 10.0,-10.0, 0.0);
    glVertex3f( 10.0, 10.0, 0.0);
    glVertex3f(-10.0, 10.0, 0.0);
    glVertex3f(-10.0,-10.0, 0.0);
  glEnd(); 

  glTranslatef( 0.0, 0.0, 1.0);
  glColor3f( 0.9, 0.0, 0.0 );

  glBegin(GL_QUADS);

   glNormal3f(1.0, 0.0, 0.0);
    glVertex3f( 1.0, 1.0,-1.0);
    glVertex3f( 1.0, 1.0, 1.0); // rechts unten
    glVertex3f( 1.0,-1.0, 1.0);
    glVertex3f( 1.0,-1.0,-1.0);

   glNormal3f(-1.0, 0.0, 0.0);
    glVertex3f(-1.0, 1.0, 1.0);
    glVertex3f(-1.0, 1.0,-1.0); // links unten
    glVertex3f(-1.0,-1.0,-1.0);
    glVertex3f(-1.0,-1.0, 1.0);

   glNormal3f(0.0,1.0,0.0);
    glVertex3f( 1.0, 1.0, 1.0);
    glVertex3f( 1.0, 1.0,-1.0); // hinten unten
    glVertex3f(-1.0, 1.0,-1.0);
    glVertex3f(-1.0, 1.0, 1.0);

   glNormal3f(0.0, -1.0, 0.0);
    glVertex3f( 1.0,-1.0,-1.0);
    glVertex3f( 1.0,-1.0, 1.0); // vorne unten
    glVertex3f(-1.0,-1.0, 1.0);
    glVertex3f(-1.0,-1.0,-1.0);

   FindNormal(-0.5,0.5,6.0,0.5,0.5,6.0,1.0,1.0,1.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f(-0.5, 0.5, 6.0);
    glVertex3f( 0.5, 0.5, 6.0); // vorne oben
    glVertex3f( 1.0, 1.0, 1.0);
    glVertex3f(-1.0, 1.0, 1.0);

   FindNormal(0.5,-0.5,6.0,-0.5,-0.5,6.0,-1.0,-1.0,1.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f( 0.5,-0.5, 6.0);
    glVertex3f(-0.5,-0.5, 6.0); // hinten oben
    glVertex3f(-1.0,-1.0, 1.0);
    glVertex3f( 1.0,-1.0, 1.0);

   FindNormal(1.0,1.0,1.0,0.5,0.5,6.0,0.5,-0.5,6.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f( 1.0, 1.0, 1.0);
    glVertex3f( 0.5, 0.5, 6.0); // rechts oben
    glVertex3f( 0.5,-0.5, 6.0);
    glVertex3f( 1.0,-1.0, 1.0);

   FindNormal(-0.5,0.5,6.0,-1.0,1.0,1.0,-1.0,-1.0,1.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f(-0.5, 0.5, 6.0);
    glVertex3f(-1.0, 1.0, 1.0); // links oben
    glVertex3f(-1.0,-1.0, 1.0);
    glVertex3f(-0.5,-0.5, 6.0);

glEnd(); 

glBegin(GL_TRIANGLES);

   FindNormal(-0.5,0.5,6.0,0.0,0.0,7.0,0.5,0.5,6.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f(-0.5, 0.5, 6.0);
    glVertex3f( 0.0, 0.0, 7.0);
    glVertex3f( 0.5, 0.5, 6.0); // vorne oben

   FindNormal(0.5,-0.5,6.0,0.0,0.0,7.0,-0.5,-0.5,6.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f( 0.5,-0.5, 6.0);
    glVertex3f( 0.0, 0.0, 7.0);
    glVertex3f(-0.5,-0.5, 6.0); // hinten oben

   FindNormal(0.5,0.5,6.0,0.0,0.0,7.0,0.5,-0.5,6.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f( 0.5, 0.5, 6.0); // rechts oben
    glVertex3f( 0.0, 0.0, 7.0);
    glVertex3f( 0.5,-0.5, 6.0);

   FindNormal(-0.5,-0.5,6.0,0.0,0.0,7.0,-0.5,0.5,6.0);
   glNormal3f(CNormal[1], CNormal[2], CNormal[3]);
    glVertex3f(-0.5,-0.5, 6.0);
    glVertex3f( 0.0, 0.0, 7.0);
    glVertex3f(-0.5, 0.5, 6.0); // links oben

glEnd;

Das Beispiel gibt es hier, damit ihr euch ansehen könnt, wie es aussieht. Also, kurze Pause, schaut euch das Ding an und dann geht es weiter...

...Alles klar? Gut. Jetzt machen wir folgendes: wir zeichnen 4 von diesen Säulen um den Mittelpunkt herum. Los geht's - viel Spaß damit.

"WAAAS? Sonst noch was?" denkt ihr euch wahrscheinlich. Verständlich, immerhin müsstet ihr 176 Flächen manuell ausrechnen und setzen. Höchst Hirnraubend. Aber wenn ihr Display Listen nutzt braucht ihr gar nichts neu zu berechnen.

Wie schon gesagt: eine Display Liste enthält eine Reihe von OpenGL Befehlen (wie "Schreibe Vertex", "Setze Licht", ...). Diese speichert man in einer Liste und man kann sie abrufen, wann und wo man will. Also speichern wir unsere Säule einmal in einer Liste und können sie so oft zeichnen, wie wir wollen. Ziemlich cool, was?

Eine Liste benötigt eine Integer Variable zum identifizieren. Wir rufen Variable := glGenLists() auf und die Variable enthält dann die Adresse der Liste. Es ist auch möglich mehrere Listen mit einem Aufruf zu erstellen. Dafür sorgt der Parameter von glGenLists.

Nach der Erzeugung der Liste müssen wir sie nur noch füllen. Dazu geben wir mit glNewList() an, welche Liste wir wie füllen wollen. Der erste Parameter ist der Name der Liste, der zweite sagt aus, ob wir die Liste nur füllen (GL_COMPILE) oder füllen und ausführen (GL_COMPILE_AND_EXECUTE) wollen.

Danach folgen beliebig viele OpenGL Kommandos. Auch Aufrufe von Prozeduren sind erlaubt (um z.B. die Normalen zu berechnen). Wenn wir fertig mit der Liste sind, schließen wir sie mit glEndList();

Wenn wir eine Liste einmal generiert haben, können wir sie mit glCallList() und dem Namen der Liste jederzeit aufrufen. Wenn wir also unsere Säule um den Nullpunkt (0,0,0) bauen und mit glTranslatef immer die Matrix verschieben, können wir die Säule hinbauen, wo wir wollen.

  glColor3f( 0.0, 0.0, 0.5 );
  glTranslatef( 0.0, 0.0, 1.0);
  glCallList(Ground);

  glColor3f( 0.9, 0.0, 0.0 );
  glTranslatef( 5.0,5.0,0.0);
  glCallList(Pillar);

  glColor3f( 0.0, 0.9, 0.0 );
  glTranslatef( 0.0,-10.0,0.0);
  glCallList(Pillar);

  glColor3f( 0.9, 0.9, 0.0 );
  glTranslatef(-10.0,0.0,0.0);
  glCallList(Pillar);

  glColor3f( 0.0, 0.9, 0.9 );
  glTranslatef(0.0,10.0,0.0);
  glCallList(Pillar);

Die Darstellung von vier(!) Säulen und dem Boden ist als Resultat kürzer geworden als die direkte Darstellung nur einer Säule direkt in der Draw_OpenGL. Hier der komplette Source Code.

Wo liegen noch Vorteile von Display Listen? Nun, jetzt müssen wir die Normalen nicht jede Runde neu berechnen. Denkt mal nach - das ist schon ziemlich unsinnig, wenn wir jedesmal beim Darstellen die gleiche Rechnung mit dem gleichen Ergebnis noch einmal machen müssen. Hier aber wird die Normale einmal beim Erstellen der Liste berechnet und das wars.

Doch das war noch nicht alles. Einige 3D Karten können die Display Listen besser abarbeiten als sequentielle Einzelbefehle. Immerhin wissen sie ja, was auf sie zukommt. Das gilt besonders bei Änderungen an der Matrix und für die Aktivierung und Deaktivierung von OpenGL Features.

So, und weil ihr es bis hierher geschafft habt, hier ein kleines Bonbon zum Spielen. Have fun!

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

Back to previous page

Useful Links









Link to us