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

Aktuelle Zeit: Sa Jul 05, 2025 13:41

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



Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mi Aug 22, 2012 11:16 
Offline
DGL Member

Registriert: Mi Aug 22, 2012 09:23
Beiträge: 5
Programmiersprache: Delphi
Hallo,

Ich hatte zunächst ein kleines OpenGL-Beispielprogramm mit einer alten TGLControl-Komponente aus OpenGL1.2 und noch nichts mit OpenGL zu tun gehabt.
Dank der Tutorials hab ich die aktuelle DGL-Version und den Render-Context auf ein Panel gelegt.
Ich muss "nur" Punkte darstellen, zuvor wurden alle mit glbegin, glVertex3dv, glend gerendert und die Farbe zwischendurch mit glColor4d geändert.
Ich würde die Punkte jetzt gerne wie im Tutorial VBO ohne glInterleaved rendern, komme aber bei
Code:
  1. glVertexPointer(4, GL_FLOAT, STRIDE, POS_OFFSET);
  2. glColorPointer(4, GL_FLOAT, STRIDE, COL_OFFSET);

nicht weiter, als letzter Parameter wird da ein Pointer erwartet.
GLVertexAttr?Pointer soll wohl aktueller sein, hab ich aber auch noch nicht gefunden, wie ich es anwenden muss, bzw. welches Attribut, möchte nur die Koordinaten als TVector3d und die Farbe als TColor übergeben.

Die Punkte werden für jede Ansichtsänderung aus einem Thread geladen. Bis der Thread fertig ist, werden die Punkte von der vorherigen Ansicht zum rendern benutzt. Ist der Thread fertig wird momentan eine TObjektliste komplett ersetzt, da sollte dann das VBO-Array ersetzt werden. Empfiehlt sich für diesen Fall bei der Funktion glBufferData GL_DYNAMIC_DRAW im letzten Parameter, oder gibts in Anbetracht, dass es sich nur um Punkte handelt, die komplett ersetzt werden noch andere Möglichkeiten?

Grüße


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 22, 2012 12:07 
Offline
DGL Member
Benutzeravatar

Registriert: Di Apr 29, 2008 18:56
Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,

das Offset einfach auf ein Pointer casten, den Rest macht OpenGL:
Code:
  1.     glVertexPointer(4, GL_FLOAT, Pointer(STRIDE, POS_OFFSET));
  2.     glColorPointer(4, GL_FLOAT, STRIDE, Pointer(COL_OFFSET));

MfG Bergmann.

_________________
Aktuelle Projekte: BumpMapGenerator, Massive Universe Online
Auf meiner Homepage gibt auch noch paar Projekte und Infos von mir.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 22, 2012 14:33 
Offline
DGL Member

Registriert: Mi Aug 22, 2012 09:23
Beiträge: 5
Programmiersprache: Delphi
Danke,

jetzt bekomm ich aber eine Zugriffsverletzung bei
Code:
  1. glDrawElements(GL_POINTS, FVBOCount, GL_UNSIGNED_?, NIL);

was für einen Typ will er da von mir haben?
Das Array ist vom Record mit den Feldern TVector3d und TVector4f für Koordinaten und Farbe.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 22, 2012 15:49 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
was für einen Typ will er da von mir haben?

glDrawElements wird für Indices verwendet. Entsprechend braucht er da den Datentyp den du für deine Indices benutzt. Üblicherweise GL_UNSIGNED_SHORT (16bit) oder GL_UNSIGNED_INT (32bit). Im Tutorial wird ja auch ein Indexbuffer benutzt.

Wolltest du vielleicht glDrawArrays benutzen?

Zitat:
Empfiehlt sich für diesen Fall bei der Funktion glBufferData GL_DYNAMIC_DRAW im letzten Parameter, oder gibts in Anbetracht, dass es sich nur um Punkte handelt, die komplett ersetzt werden noch andere Möglichkeiten?

Ggf. kann es Sinn machen glBufferSubData zu verwenden, wenn du nur einen Teil der Daten ändern willst (etwa nur die Farben, aber die Position behalten). In dem Fall würde man dann die Daten für Vertices nicht interleaven sondern hintereinander in den VBO legen. Also z.B. erst sämtliche Positionen, dann die Farben. Stride ist dann Null. So brauchst du dann z.B. nur den hinteren Teil des VBOs neu schreiben.

Ansonsten kann glMapBuffer / glUnmapBuffer noch eine Option sein. Dabei wird die Speicher Verwaltung von OpenGL übernommen, d.h. du musst nicht selbst einen Speicherbereich anlegen und an OpenGL übergeben, sondern du bekommst einen Pointer wo du dann reinschreiben darfst. Wenn du deine Daten sowieso noch für OpenGL aufbereiten musst kann das möglicherweise effizienter sein. (*)

[edit]
(*) Wenn du deine Daten erst aufbereiten musst, musst du bei einem glBufferData zuerst selbst einen Speicherbereich anlegen und die Daten darein kopieren. glBufferData bekommt dann einen Pointer auf deine Daten. Die Daten werden also mindestens zweimal angefasst. Mit glMapBuffer kannst du die Daten direkt dahin schreiben wo sie hin sollen, das spart einen Kopiervorgang.
[/edit]

_________________
Yeah! :mrgreen:


Zuletzt geändert von Coolcat am Do Aug 23, 2012 10:03, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 09:21 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Coolcat hat geschrieben:
Beim glUnmapBuffer muss OpenGL nicht warten, es kann einfach den Copy-Befehl zum senden der Daten an die Grafikkarte auf die Command-Queue werfen.

Hm. Wie schonmal andersweitig erwähnt ist die chance, dass der Speicher tatsächlich gemappt wird, man also direkt in den GRAM schreibt, größer ;). Hast du dazu mehr Informationen? Ich hätte das nämlich gerne mal geklärt :).

Coolcat hat geschrieben:
Wichtig ist natürlich das du glMapBuffer mit GL_READ_ONLY benutzt[…]
Did you mean: GL_WRITE_ONLY? ;)

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 09:27 
Offline
DGL Member

Registriert: Mi Aug 22, 2012 09:23
Beiträge: 5
Programmiersprache: Delphi
Coolcat hat geschrieben:
Wolltest du vielleicht glDrawArrays benutzen?

Wollte mich eigentlich an das Tutorial halten, dachte glDrawArrays wär für Display-Listen.

Coolcat hat geschrieben:
Zitat:
Empfiehlt sich für diesen Fall bei der Funktion glBufferData GL_DYNAMIC_DRAW im letzten Parameter, oder gibts in Anbetracht, dass es sich nur um Punkte handelt, die komplett ersetzt werden noch andere Möglichkeiten?

Ggf. kann es Sinn machen glBufferSubData zu verwenden, wenn du nur einen Teil der Daten ändern willst (etwa nur die Farben, aber die Position behalten). In dem Fall würde man dann die Daten für Vertices nicht interleaven sondern hintereinander in den VBO legen. Also z.B. erst sämtliche Positionen, dann die Farben. Stride ist dann Null. So brauchst du dann z.B. nur den hinteren Teil des VBOs neu schreiben.

Der Fall tritt bei mir nicht auf, ich will die Punkte nur solange wieder benutzen, bis neue geladen sind und diese dann komplett ersetzen, aber ich werds mal ausprobieren, obs mir wegen der Zugriffsverletzung weiter hilft.

Coolcat hat geschrieben:
Ansonsten kann glMapBuffer / glUnmapBuffer noch eine Option sein. Dabei wird die Speicher Verwaltung von OpenGL übernommen, d.h. du musst nicht selbst einen Speicherbereich anlegen und an OpenGL übergeben, sondern du bekommst einen Pointer wo du dann reinschreiben darfst. Wenn du deine Daten sowieso noch für OpenGL aufbereiten musst kann das möglicherweise, je nach Treiber effizienter sein. (*)

(*) Das ist allerdings reine Spekulation. Bei einem glBufferData muss OpenGL die Daten sofort an die Grafikkarte senden oder zumindest kopieren, den OpenGL muss davon ausgehen, dass du den Speicherbereich direkt nach dem Aufruf von glBufferData freigibst oder anderweitig benutzt. D.h. entweder werden die Daten unnötig einmal kopiert, oder glBufferData muss warten bis die Grafikkarte Zeit hat die Daten anzunehmen (GPU Sync). Beides eher schlecht.
Beim glUnmapBuffer muss OpenGL nicht warten, es kann einfach den Copy-Befehl zum senden der Daten an die Grafikkarte auf die Command-Queue werfen. Hier besteht keine Gefahr, dass der Speicher anderweitig benutzt wird. Wenn dann irgendwann die Command-Queue abgearbeitet wurde (spätestens beim swappen des Framebuffers am Ende des Frames) und die Daten auf der Grafikkarte liegen, kann der Speicher freigegeben werden. Aber das macht OpenGL intern, die Anwendung (also du) braucht sich darum nicht kümmern. Wichtig ist natürlich das du glMapBuffer mit GL_READ_ONLY benutzt, sonst ist dieser potentielle Vorteil natürlich dahin. Wie gesagt, reine Spekulation meinerseits, ob der Treiber das wirklich so umsetzt liegt am Treiber ;)

Werds dann mal wie bei GL ARB vertex buffer object beschrieben ausprobieren, wär aber auch erstmal froh, wenns mit glbufferdata läuft.

Coolcat hat geschrieben:
Zitat:
was für einen Typ will er da von mir haben?

glDrawElements wird für Indices verwendet. Entsprechend braucht er da den Datentyp den du für deine Indices benutzt. Üblicherweise GL_UNSIGNED_SHORT (16bit) oder GL_UNSIGNED_INT (32bit). Im Tutorial wird ja auch ein Indexbuffer benutzt.

Achso, weil ich die Daten sowieso nicht verändern will, dachte ich, es würde auch ohne Indices gehn.
Bekomm aber auch mit glDrawArrays ne Zugriffsverletzung, hier mal mein OpenGL-Code:

Code:
  1.  
  2. //interface:
  3.   TVBOPnt = packed record
  4.     P1 : TVector3d;
  5.     Color : TVector4f;
  6.   end;
  7.   TVBOPoints = Array of TVBOPnt;
  8.  
  9. //private Variablen vom Form:
  10.     FVBO : TVBOPoints;
  11.     FIDVBO : Cardinal;       // Opengl-"Handles" für VBO- und Indexpuffer
  12.     FVBOCount : Integer;
  13.  
  14. //implementation:
  15. const
  16.   POS_OFFSET  =  0;
  17.   COL_OFFSET  =  SizeOf(TVector3d);
  18.   STRIDE      =  SizeOf(TVBOPnt);
  19.  
  20. //Render-Prozedur:
  21.     //...Sichteinstellungen usw. ...
  22.     glBindBuffer(GL_ARRAY_BUFFER, FIDVBO);
  23.  
  24.     glEnableClientState(GL_VERTEX_ARRAY);
  25.     glEnableClientState(GL_COLOR_ARRAY);
  26.  
  27.     glVertexPointer(3, GL_DOUBLE, STRIDE, @FVBO[0].P1);
  28.     glColorPointer(4, GL_FLOAT, STRIDE, @FVBO[0].Color);
  29.  
  30.     glDrawArrays(GL_POINTS, 0, FVBOCount*STRIDE);
  31.  
  32.     glDisableClientState(GL_COLOR_ARRAY);
  33.     glDisableClientState(GL_VERTEX_ARRAY);
  34.  
  35. //Füllen des Arrays:
  36.   FDLG.FVBOCount := PntList.Count;
  37.   SetLength(FDLG.FVBO, FDLG.FVBOCount);
  38.   FillChar(FDLG.FVBO[0], FDLG.FVBOCount * SizeOf(TVBOPnt), #0);
  39.   for i := 0 to FDLG.FVBOCount - 1 do
  40.   begin
  41.     FDLG.FVBO[i].P1 := TGLPnt(PntList[i]).P1;
  42.     FDLG.FVBO[i].Color := ColorVec(TGLPnt(PntList[i]).Color);
  43.   end;
  44.  
  45.   glGenBuffers(1, @FDLG.FIDVBO);
  46.   glBindBuffer(GL_ARRAY_BUFFER, FDLG.FIDVBO);
  47.   glBufferData(GL_ARRAY_BUFFER, FDLG.FVBOCount*SizeOf(TGLPnt), @FDLG.FVBO[0], GL_DYNAMIC_DRAW);
  48.  
  49. //FormDestroy:
  50.   glDeleteBuffers(1,@FIDVbo);
  51.  


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 10:12 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Achso, weil ich die Daten sowieso nicht verändern will, dachte ich, es würde auch ohne Indices gehn.

Wenn du glDrawElements benutzen willst muss ein Indexbuffer gebunden sein. Dieser wird dann als Input benutzt. Da du aber Punkte renderst sind Indices eher weniger sinnvoll, es sei den du willst aus irgendeinem Grund häufig Punkte mehrfach rendern.

Zitat:
Bekomm aber auch mit glDrawArrays ne Zugriffsverletzung, hier mal mein OpenGL-Code:

glDrawArrays will die Anzahl der Vertices haben, nicht die Größes des Buffers. Also ohne STRIDE würde ich sagen:
Code:
  1. glDrawArrays(GL_POINTS, 0, FVBOCount);


Zitat:
Did you mean: GL_WRITE_ONLY? ;)

Äh, natürlich...sry.

Zitat:
Hm. Wie schonmal andersweitig erwähnt ist die chance, dass der Speicher tatsächlich gemappt wird, man also direkt in den GRAM schreibt, größer ;). Hast du dazu mehr Informationen? Ich hätte das nämlich gerne mal geklärt :).

Nein, ich habe nicht mehr Infos dazu, alles nur Spekulation meinerseits. Von MemoryMapping wusste ich bisher nix. Ich habe meinen Posten oben mal editiert. Denn auch in dem Fall kann glMapBuffer sinnvoller sein, weil man einen Kopiervorgang spart.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 11:00 
Offline
DGL Member

Registriert: Mi Aug 22, 2012 09:23
Beiträge: 5
Programmiersprache: Delphi
Danke, beim glDrawArrays tritt die Zugriffsverletzung jetzt nicht mehr auf, aber es funktioniert trotzdem noch nicht, beim Debuggen komm ich nur bis zur Endlosschleife des modalen Forms, wenn ich dann laufen lasse, tritt wieder eine Zugriffsverletzung auf :?

Code:
  1.  
  2. //interface:
  3.   TVBOPnt = packed record
  4.     P1 : TVector3d;
  5.     Color : TVector4f;
  6.   end;
  7.   TVBOPoints = Array of TVBOPnt;
  8.  
  9. //private Variablen vom Form:
  10.     FVBO : TVBOPoints;
  11.     FIDVBO : TGLuint;       // Opengl-"Handles" für VBO- und Indexpuffer
  12.     FVBOCount : Integer;
  13.  
  14. //implementation:
  15. const
  16.   POS_OFFSET  =  0;
  17.   COL_OFFSET  =  SizeOf(TVector3d);
  18.   STRIDE      =  SizeOf(TVBOPnt);
  19.  
  20. //FormCreate:
  21.   DC:= GetDC(View.Handle);
  22.   if not InitOpenGL then Application.Terminate;
  23.   RC:= CreateRenderingContext( DC, [opDoubleBuffered], 32, 24, 0, 0, 0, 0);
  24.   ActivateRenderingContext(DC, RC);
  25.  
  26.   glClearColor(0, 0, 0, 0.0);       //Hintergrundfarbe
  27.   glEnable(GL_DEPTH_TEST);          //Tiefentest aktivieren
  28.   glDisable(GL_CULL_FACE);           //Backface Culling deaktivieren
  29.  
  30.   glEnable(GL_LIGHTING);
  31.   glEnableClientState(GL_VERTEX_ARRAY);
  32.   glEnableClientState(GL_COLOR_ARRAY);
  33.  
  34.   glGenBuffers(1, @FIDVBO);
  35.   glBindBuffer(GL_ARRAY_BUFFER, FIDVBO);
  36.  
  37. //Füllen des Arrays:
  38.   FDLG.FVBOCount := PntList.Count;
  39.   SetLength(FDLG.FVBO, FDLG.FVBOCount);
  40.   FillChar(FDLG.FVBO[0], FDLG.FVBOCount * STRIDE, #0);
  41.   for i := 0 to FDLG.FVBOCount - 1 do
  42.   begin
  43.     FDLG.FVBO[i].P1 := TGLPnt(PntList[i]).P1;
  44.     FDLG.FVBO[i].Color := ColorVec(TGLPnt(PntList[i]).Color);
  45.   end;
  46.  
  47.   glBufferData(GL_ARRAY_BUFFER, FDLG.FVBOCount*STRIDE, @FDLG.FVBO[0], GL_DYNAMIC_DRAW);
  48.  
  49. //Render-Prozedur:
  50.     //...Sichteinstellungen usw. ...
  51.  
  52.     glVertexPointer(3, GL_DOUBLE, STRIDE, @FVBO[0].P1);
  53.     glColorPointer(4, GL_FLOAT, STRIDE, @FVBO[0].Color);
  54.  
  55.     glDrawArrays(GL_POINTS, 0, FVBOCount);
  56.  
  57. //FormDestroy:
  58.   glDisableClientState(GL_COLOR_ARRAY);
  59.   glDisableClientState(GL_VERTEX_ARRAY);
  60.   glDeleteBuffers(1,@FIDVbo);
  61.  
  62.   glDisable(GL_LIGHTING);
  63.   DeactivateRenderingContext;
  64.   DestroyRenderingContext(RC);
  65.   ReleaseDC(Handle, DC);
  66.  

€ hab auch schon versucht die Farbe rauszunehmen, hilft aber auch nicht.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 12:14 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Code:
  1.     glVertexPointer(3, GL_DOUBLE, STRIDE, @FVBO[0].P1);
  2.     glColorPointer(4, GL_FLOAT, STRIDE, @FVBO[0].Color);

Wenn ein VBO gebunden ist, wird der letzte Parameter als Offset vom Anfang des Buffers interpretiert. Die Daten hast du ja schon mit glBufferData an die Grafikkarte geschickt! Der Offset für glVertexPointer ist 0, da die Position als erstes kommt. Der Offset für glColorPointer ist SizeOf(TVector3d). Du hast dir ja da auch schon Konstanten POS_OFFSET und COL_OFFSET angelegt.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 14:43 
Offline
DGL Member

Registriert: Mi Aug 22, 2012 09:23
Beiträge: 5
Programmiersprache: Delphi
hatte diese Variante irgendwo im Forum gelesen, wo´s dann funktioniert hat, aber dann nicht wieder zurück geändert, nachdems auch nicht ging.

Habs jetzt ohne glMapBuffer hinbekommen, es lag daran, dass ich das Array in einen anderen Thread gefüllt habe, kam aber erst drauf, weil glmapbuffer nil ausgespuckt hat.

mal sehn ob ichs für glmapbuffer auch noch hinkriege.

Danke nochmal.

€: Muss ich für glMapBuffer beim Rendern auch noch
Code:
  1.     glVertexPointer(3, GL_DOUBLE, STRIDE, Pointer(POS_OFFSET));
  2.     glColorPointer(4, GL_FLOAT, STRIDE, Pointer(COL_OFFSET));

aufrufen?
Im Tutorial Vertexbufferobject wird glInterleaved aufgerufen, bei GL ARB vertex buffer object steht nichts vorm Rendern.
Funktioniert aber im Moment beides nicht mit glMapBuffer. Ich habe noch mein Record mit TVector3d und TVector4f, könnte es daran liegen, dass man die Doubles bzw. Floats einzeln übergeben muss?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 23, 2012 16:35 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
glMapBuffer ist ja nur ein anderer Weg die Daten in den Buffer zu kriegen. Mit dem Rendern hat das nichts zu tun, d.h. du kannst genauso rendern wie du es mit glBufferData tun würdest.

Zitat:
Funktioniert aber im Moment beides nicht mit glMapBuffer. Ich habe noch mein Record mit TVector3d und TVector4f, könnte es daran liegen, dass man die Doubles bzw. Floats einzeln übergeben muss?

Du musst irgendwie die Daten in den Speicherbereich schreiben den dir glMapBuffer gibt. Übrigens musst du einmal glBufferData mit NIL als Daten aufrufen um den VBO der gewünschten Größe zu erzeugen. Mit glMapBuffer kannst du nur Daten aus einem existierenden Buffer lesen/schreiben.

_________________
Yeah! :mrgreen:


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 10 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:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 16 Queries | GZIP : On ]