Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 04, 2025 15:07

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: glGenLists - Fragen
BeitragVerfasst: Do Aug 06, 2009 20:38 
Offline
DGL Member
Benutzeravatar

Registriert: Do Jun 18, 2009 07:17
Beiträge: 44
Wohnort: Gießen/Hessen
Ich versuche gerade eine SkyBox so zu erweitern das man aus verschiedenen Unterverzeichnissen quasi "On The Fly" laden kann.

Um das zu realisieren habe ich ein Klassen-Typen geschrieben:

Code:
  1. TOGLPictureBox = class (TObject)
  2.     Folder: AnsiString;                    { the absolute image folder }
  3.     Title: AnsiString;                     { the last folder of the image folder }
  4.     DisplayID: TGLuint;                    { the display ID }
  5.     SkyBoxTexture : Array[0..5] of TGLBmp; { the loaded textures }
  6.   end;    


der alle Daten auf dem Heap aufnehmen soll, das Laden funktioniert auch einwandfrei, in einer Liste werden die geladenen Verzeichnisse angezeigt. Aber auf der Oberfläche wird nichts anzeigt.

Ich gehe wie folgt vor:

Code:
  1. procedure TGLForm.LoadSkyBoxFromFolder;
  2. var
  3.   Box: TOGLPictureBox;
  4.   I: Integer;
  5.   FolderList: TStrings;
  6. begin
  7.     FolderList := TStringList.Create;   { create the img folder list}
  8.  
  9.     FindAllImageFolders(FolderList);    { fill the img folder list, contains
  10.                                           now all application sub folders }
  11.  
  12.     for I := 0 to FolderList.Count -1 do { iterate through the folders }
  13.     begin
  14.       Box := TOGLPictureBox.Create;      { create the PictureBox data holder }
  15.       Box.Folder:= FolderList[I];
  16.       Box.Title := ExtractFileName(
  17.                      FolderList[I]);     { extract the last folder name }
  18.       LoadSkyBox(Box);                   { Load the textures into SkyBoxTexture array
  19.                                            calls the function GenerateSkyBox -> create
  20.                                            the real box and bind the textures}
  21.  
  22.       if I = 0 then
  23.          FActiveListID := Box.DisplayID; { set the first display list active }
  24.       ListBox1.Items.AddObject(          { add the PictureBox obejct to ListBox }
  25.               Box.Title,                 { - display folder name }
  26.               Box);                      { - assign object to name }
  27.     end;
  28.     FolderList.Free;                     { clean up unused ojects }
  29. end;


die entsprechende LoadSkyBox procedure:

Code:
  1. procedure TGLForm.LoadSkyBox(Box: TOGLPictureBox);
  2. const
  3.  // this is the array that holds the names of all skybox textures without their extensions
  4.  SkyBoxName : array[0..5] of String = ('BK', 'FR', 'DN', 'UP', 'LF', 'RT');
  5. var
  6.  i : Integer;
  7.  strBuff: string;
  8. begin
  9. // Now we load the images and generate our textures
  10. for i := 0 to High(Box.SkyBoxTexture) do
  11.  begin
  12.  Box.SkyBoxTexture[i] := TGLBmp.Create;
  13.  strBuff := Box.Folder + DirectorySeparator + SkyBoxName[i]+'.bmp';
  14.  if not FileExists(strBuff) then MsgBox('DEBUG','FileNot exist: ' + strBuff);
  15.  Box.SkyBoxTexture[i].LoadImage(buff);
  16.  
  17.  // We need to clamp our textures so that our borders look right
  18.  Box.SkyBoxTexture[i].SetTextureWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
  19.  Box.SkyBoxTexture[i].GenTexture(False, True);
  20.  end;
  21.  GenerateSkyBox(512, 512, 512, Box);
  22. end;


und ein Auszug aus der GenerateSkyBox:

Code:
  1. procedure TGLForm.GenerateSkyBox(pWidth, pHeight, pLength : TGLFloat;
  2.          Box: TOGLPictureBox);
  3. var
  4.  px,py,pz : TGLFloat;
  5. begin
  6.   Box.DisplayID := glGenLists(1);
  7.   glNewList(SkyBox, GL_COMPILE);
  8.  
  9.  px := - pWidth  / 2;
  10.  py := - pHeight / 2;
  11.  pz := - pLength / 2;
  12.  // Back
  13.  Box.SkyBoxTexture[0].Bind;
  14.  glBegin(GL_QUADS);
  15.   glTexCoord2f(0, 0); glVertex3f(px,          py,           pz);
  16.   glTexCoord2f(0, 1); glVertex3f(px,          py + pHeight, pz);
  17.   glTexCoord2f(1, 1); glVertex3f(px + pWidth, py + pHeight, pz);
  18.   glTexCoord2f(1, 0); glVertex3f(px + pWidth, py,           pz);
  19.  glEnd;        
  20. .
  21. .
  22. .
  23. end;


und die Verwendung der DisplayID

Code:
  1. procedure TGLForm.DrawScene;
  2. begin
  3.   glMatrixMode(GL_MODELVIEW);
  4.   glLoadIdentity;
  5.   // As the Skybox will fill the entire screen, we will only have to clear
  6.   // the depth buffer and not the color buffer
  7.   glClear(GL_COLOR_BUFFER_BIT);
  8.   glClear(GL_DEPTH_BUFFER_BIT);
  9.   glRotatef(xrot, 1, 0, 0);
  10.   glRotatef(yrot, 0, 1, 0);
  11.   // Call the Displaylist of our Skybox
  12.   glCallList(FActiveListID);
  13.   SwapBuffers(FDC);
  14. end;


Ich muss dazusagen, dass das Grundgerüst aus dem Tutorial SkyBoxen stammt, ich habe lediglich die Funktionssignaturen an meine Bedürfnisse angepasst, und ein paar kleine Änderungen vorgenommen.

Ich vermute das man die Texturen nicht dauerhaft an glGenLists/glNewList binden kann, daher ist dann auch keine Textur aktiv die Angezeigt werden kann. Ich habe auch keine Ausgabe, wenn nur ein Unterverzeichnis angegeben habe das Ergebnis ist das Gleiche.

Tut mir leid soviel Source-Code zu päsentieren, aber ich glaube ich habe da ein echtes Verständisproblem mit den DisplayListen.

:roll:

_________________
Gruß Andreas (aka DeepCopy) - Sic Luceat Lux

Classified Directive: initialization write in function for finalization, repeat until public case uses begin, if not case type as default, var in virtual override for while, in case of class type type asm until read begin.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 07, 2009 00:53 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Code:
  1.  
  2. Box.DisplayID := glGenLists(1);
  3. glNewList(SkyBox, GL_COMPILE);
  4.  


sollte auch so aussehen:

Code:
  1.  
  2. Box.DisplayID := glGenLists(1);
  3. glNewList(Box.DisplayID, GL_COMPILE);
  4.  


OpenGL will ja auch schliesslich wissen welche Liste erstellt werden soll.
Des weiteren fehlt ein 'glEndList'. Welches du aber wahrscheinlich weggekürzt hast.

Allerdings würde ich auch das Laden von Texturen oder Objekten vom Erstellen selbiger trennen.
Eine Skybox ist schliesslich nichts anderes als ein Würfel, nur dass er andersrum gezeichnet werden muss, wegen Backfaceculling.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 07, 2009 08:58 
Offline
DGL Member
Benutzeravatar

Registriert: Do Jun 18, 2009 07:17
Beiträge: 44
Wohnort: Gießen/Hessen
Du bist mein persönlicher Held :wink: !

Zitat:
sollte auch so aussehen:

Code:
  1. Box.DisplayID := glGenLists(1);
  2. glNewList(Box.DisplayID, GL_COMPILE);
  3.  


Daran war ich fast am verzweifeln - du hast ein sehr gutes Auge - , Danke damadmax!


Zitat:
Allerdings würde ich auch das Laden von Texturen oder Objekten vom Erstellen selbiger trennen.
Eine Skybox ist schliesslich nichts anderes als ein Würfel, nur dass er andersrum gezeichnet werden muss, wegen Backfaceculling.


Das habe ich nicht verstanden, wie meinst du das? - Und was hat das mit Backfaceculling zu tun?

_________________
Gruß Andreas (aka DeepCopy) - Sic Luceat Lux

Classified Directive: initialization write in function for finalization, repeat until public case uses begin, if not case type as default, var in virtual override for while, in case of class type type asm until read begin.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 07, 2009 10:34 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Er meint, dass es ein Unterschied ist, ob man den Würfel von innen sieht (aka "SkyBox") oder ob man den Würfel von außen sieht.

Würfel von innen sichtbar: Alle Quads müssen nach innen zeigen (das hat etwas mit dem Umlaufsinn ihrer Eckpunkte zu tun)
Würfel von außen sichtbar: Alle Quads müssen nach außen zeigen.

Daraus folgt: wenn Du eine Skybox von außen siehst und gleichzeitig Backface-Culling eingeschaltet hast, ist er unsichtbar, weil der ganze Würfel dem Backface Culling zum Opfer fällt und daher nicht gezeichnet wird.


Und er meint, dass man das Laden der Strukturen vom Erstellen der Listen trennen sollte. Das betrifft Dich eigentlich nur, wenn Du vorhast, etwas Komplizierters zu bauen, denn dann werden auch andere Dinge wichtig, wie zum Beispiel Übersichtlichkeit des Codes und Performance.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 07, 2009 10:51 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
@Traude: Genau. So schön kann ich einfach nicht formulieren. Danke


Auf die Zeichenrichtung sollte man von anfang an achten. Falls man später erst das Culling aktiviert, könnte das sehr unschön aussehen und auch eine Heidenarbeiten sein das überall in den Tiefen des Quellcodes zu finden und zu korrigieren.

Noch was zu den Quads. Ich würde Dreiecke bevorzugen. Und diese nicht direkt in eine Displayliste ausgeben sondern eine gesonderte (geerbte) (z.b.)'buildObject' Funktion verwenden, die die Liste erstellt. Während der Erstellung deines Objekts packst du alle Daten (Vertex, Texturkoordinaten, Farbe, etc.pp) in Arrays und erst die buildObject Funktion erstellt die Displayliste. Somit hat man zum einen weniger glBegins und glEnd und zum anderen lässt es sich später sehr einfach auf VBOs umstellen.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 07, 2009 13:52 
Offline
DGL Member
Benutzeravatar

Registriert: Do Jun 18, 2009 07:17
Beiträge: 44
Wohnort: Gießen/Hessen
Ok, eine menge Hinweise... danke erstmal an Euch!

Also eins nach dem Anderen:

Zitat:
Und er meint, dass man das Laden der Strukturen vom Erstellen der Listen trennen sollte. Das betrifft Dich eigentlich nur, wenn Du vorhast, etwas Komplizierters zu bauen, denn dann werden auch andere Dinge wichtig, wie zum Beispiel Übersichtlichkeit des Codes und Performance.


@Traude: Kannst du mir dazu ein Praxisbeispiel nennen?


Zitat:
Während der Erstellung deines Objekts packst du alle Daten (Vertex, Texturkoordinaten, Farbe, etc.pp) in Arrays und erst die buildObject Funktion erstellt die Displayliste.


@damadmax: Also etwa so:

Code:
  1. type
  2. TOpenGLObject = class (TObject)
  3.   private
  4.     FIsBuildObject: Boolean;
  5.     FPosition: TVertex3f;
  6.     FRotation: TMatrix4f;
  7.   public
  8.     procedure buildObject; abstract;
  9.     procedure drawObject; virtual;
  10. end;
  11.  
  12. TBaum = class(TOpenGLObject)
  13.   private
  14.     FBaumTexture: Array of TGLBitmap;
  15.     FBaumTextureCoords: Array of TVertex2f;
  16.     FBaumObject: Array of TVertex4f;
  17.   public
  18.     procedure buildObject; override;
  19.     procedure drawObject; override;
  20. end;
  21.  
  22. implementation
  23.  
  24. procedure TOpenGLObject.drawObject; virtual;
  25. begin
  26.    if not FIsBuildObject then buildObject;
  27. end;
  28.  
  29.  


Meine Frage nun, wann soll buildObject aufgerufen werden? Vor dem Aufruf von drawObject, oder beim Aufruf von drawObject wie oben gezeigt?

Ich denke wann drawObject aufgerufen wird ist schon klar, immer in der Render procedure.

Zitat:
Somit hat man zum einen weniger glBegins und glEnd und zum anderen lässt es sich später sehr einfach auf VBOs umstellen.


Wieso habe ich weniger glBegin und glEnd? Die Anzahl von glBegin und glEnd in der Displayliste sind doch gleich, oder? Das mit den VBO's hab ich mir mal angesehen, aber noch nicht vollständig verstanden, es soll wohl die Vorzüge von VertexArrays mit Displaylisten vereinen.
Welchen Vorteil hätte ich denn konkret davon?

_________________
Gruß Andreas (aka DeepCopy) - Sic Luceat Lux

Classified Directive: initialization write in function for finalization, repeat until public case uses begin, if not case type as default, var in virtual override for while, in case of class type type asm until read begin.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 07, 2009 19:01 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Traude hat geschrieben:
Und er meint, dass man das Laden der Strukturen vom Erstellen der Listen trennen sollte. Das betrifft Dich eigentlich nur, wenn Du vorhast, etwas Komplizierters zu bauen, denn dann werden auch andere Dinge wichtig, wie zum Beispiel Übersichtlichkeit des Codes und Performance.
DeepCopy hat geschrieben:
@Traude: Kannst du mir dazu ein Praxisbeispiel nennen?

Das Laden der Strukturen unterscheidet sich vom Erstellen der Listen dadurch, dass man beim Listen erstellen einen Rendering Context braucht und beim Laden von der Platte nicht. Dadurch ergibt sich die Möglichkeit, das Laden von Platte mittels Threads zu beschleunigen, was bei Listenerstellen nicht geht, denn man kann nicht auf OpenGL-Befehle aus einem anderen Thread zugreifen.

Oder Du möchtest später - wie oben schon erwähnt wurde - alles in ein VBO laden, dann müsstest Du warten, bis der Ladevorgang für alle Objekte fertig ist, damit man sie alle zusammen an die Grafikkarte schicken kann.

Das sind beides gute Argumente dafür, das Laden in den Hauptspeicher vom Laden in den Grafikspeicher nicht in der gleichen Prozedur zu erledigen.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.012s | 17 Queries | GZIP : On ]