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

Aktuelle Zeit: So Jun 16, 2024 09:18

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



Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
BeitragVerfasst: Di Apr 02, 2013 18:57 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Hallo,

man möge mir verzeihen ein weiteres neues Thema zu eröffnen, aber da es ja nicht mehr um VBO mit glVBO geht dachte ich das passt besser.

Wie der Name des neuen Fadens schon sagt, geht es um diesen Wiki Beitrag:VBO ohne glInterleavedArrays

Mit dem ist es sogar mir gelungen VBO's zu realisieren, nachdem ich vorher mehfach an Tutorial Vertexbufferobject gescheitert bzw verzweifelt bin und auch mit glVBO keinen wirklichen Erfolg für meine Anwendung erzielen konnte.

Da meine derzeitige Lösung auf NVIDIA zu einer Zugriffsverletzung geführt hat und ich auch einige Teile des WIKI beitrags nicht verstanden habe, zeige ich mal meine an meine Anwendung adaptierte Lösung mit der Bitte das man mir mögliche Fehler oder Optimierungsmöglichkeiten, und vor allem sachdienliche Hinweise, wieso das auf NVIDIA zickt und auf ATI läuft gibt.

Also hier mal die Konstanten analog zu Traudes Vorgehensweise:

Code:
  1.  
  2. type
  3.   TVertex = record
  4.   VX, VY, VZ: GLfloat;
  5. end;
  6.  
  7. type TVBOVertexPack = packed record
  8.   Vertex,
  9.   Normal:TVertex; //Das Original im Wiki hat Position, Color +Platzhalter.. ich habe Vertis und Normis
  10. end;
  11.  
  12. TVBOBuffer = array of TVBOVertexPack;
  13. TIndexBuffer = array of Cardinal; //hier habe ich Cardinal gewählt statt "Word"
  14.  
  15. const
  16.  
  17. POS_OFFSET = 0;
  18. NORM_OFFSET = SizeOf(TVertex); //da ich keinen TVector4D habe nehme ich sizeof(TVertex)
  19. STRIDE = SizeOf(TVBOVertexPACK);


In meiner Klasse Model Klasse habe ich dann folgende Variablen zugefügt:

Code:
  1.  
  2.     VBOBuffer : TVBOBuffer;
  3.     IndexBuffer : TIndexBuffer;
  4.     VertexBuffSize,
  5.     IndexBuffSize,
  6.     IndexCount,
  7.     IDVBO,IDINDEX:Cardinal; //alles weitestgehend identisch zum Wiki Beitrag
  8.  


Hiermit befülle ich das VBO aus meinen bisherigen Arrays:

Code:
  1. procedure FillVBO;
  2. var Anzahl:integer;
  3. var i: integer;
  4. begin
  5.   Anzahl := length(model.varray);
  6.   model.indexcount := Anzahl;
  7.   model.VertexBuffSize := model.IndexCount*SizeOf(TVBOVertexPack);
  8.   model.IndexBuffSize := model.IndexCount*SizeOf(Cardinal);
  9.   SetLength(model.VBOBuffer,model.IndexCount);
  10.   FillChar(model.VBOBuffer[0],Length(model.VBOBuffer)*SizeOf(TVBOVertexPack),#0);
  11.   for i  := 0 to Anzahl-1 do
  12.   begin
  13.     With model.VBOBuffer[i] do
  14.     begin
  15.       With Vertex do Begin VX := model.varray[i].VX; VY := model.varray[i].VY; VZ := model.varray[i].VZ; End;
  16.       With Normal do Begin VX := model.narray[i].VX; VY := model.narray[i].VY; VZ := model.narray[i].VZ; End;
  17.     end;
  18.   end;
  19.   glGenBuffers(1,@model.IDVbo);
  20.   glBindBuffer(GL_ARRAY_BUFFER, model.IDVbo);
  21.   glBufferData(GL_Array_Buffer,model.VertexBuffSize,@model.VBOBuffer[0],GL_STATIC_DRAW);
  22.   SetLength(model.IndexBuffer,model.IndexCount);
  23.   for i := 0 to Anzahl-1 do
  24.   begin
  25.     model.IndexBuffer[i] := i;
  26.   end;
  27.   glGenBuffers(1,@model.IDIndex);
  28.   glBindBuffer(GL_Element_ARRAY_BUFFER, model.IDIndex);
  29.   glBufferData(GL_Element_ARRAY_BUFFER, model.IndexBuffSize,@model.IndexBuffer[0],GL_STATIC_DRAW);
  30. end;


Hier habe ich auch ein paar Fragen:
1.) Zeile 10 : Was genau wird hier gemacht, mir sagt das nichts, ich habe es mehr oder weniger blind übernommen..
2.) Zeile 19 und 27: hier wird das VBO doch erstellt oder? was bedeutet die 1?

ok, das Befüllen hat ja offensichtlich geklappt, schauen wir nach dem Rendern:
zunächst habe ich versucht es wie im WIKI zu machen, als dort steht:
Zitat:
glBindBuffer(GL_ARRAY_BUFFER, IDVbo);

Nötige Zeiger setzen

glVertexPointer(4, GL_FLOAT, STRIDE, POS_OFFSET);
glColorPointer(4, GL_FLOAT, STRIDE, COL_OFFSET);

Indexpuffer binden

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IDIndex);


ich habe das versucht auf mich angepasst wie folgt zu machen:

Code:
  1.  
  2.     glBindBuffer(GL_ARRAY_BUFFER, model.IDVBO);
  3.     glVertexPointer(3,GL_Float,STRIDE, POS_OFFSET); // bringt Fehler
  4.     glNormalPointer(3,GL_FLOAT,STRIDE, NORM_OFFSET); // bringt Fehler
  5.  

und bekam prompt vom Compiler 2x
Zitat:
E2010 Inkompatible Typen: 'Pointer' und 'Integer'

in den Zeilen 3 und 4...

nach einigem Probieren und mit altem Code von mir vergleichen habe ich dann auf

Code:
  1.    
  2.     glBindBuffer(GL_ARRAY_BUFFER, model.IDVBO);
  3.     glVertexPointer(3,GL_FLOAT,STRIDE,@model.VBOBuffer[0].vertex);
  4.     glNormalPointer(GL_FLOAT,STRIDE,@model.VBOBuffer[0].normal);
  5.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.IDIndex);
  6.  

Hierzu habe ich auch eine Frage:
3.) Warum ist beim glNormalPointer keine 3, vornedran?

danach zeichne ich die Szene endlich:

Code:
  1. glDrawElements(GL_TRIANGLES, model.IndexCount,GL_UNSIGNED_INT,nil);

im Gegensatz zu Traude muß ich hier GL_UNSIGNED_INT nehmen dieweil ich wohl vorn statt Word auch Cardinal genommen habe.

bis hierhin war mein Bildschirm leer, nix drauf, nada

aber Traude hat ja noch 4 Code-Zeilen im Wiki stehn:
Zitat:
Finalize(IndexBuffer);
Finalize(VBOBuffer);
glDeleteBuffers(1,@IDVbo);
glDeleteBuffers(1,@IDIndex);


da ich keine Ahnung habe wohin damit habe ich sie in die Renderschleife gepackt, was zunächst zu einer Zugriffsverletztung führte.. Traude schreibt dazu leider nichts, es geht dort nur noch um Supermärkte und Jumbojets..

Durch Try And Error habe ich festgestellt das die glDeleteBuffers die Zugriffsverletzung verursachen und das das Finalize(VBOBuffer) mir meine Daten auf den Schirm zaubert.. Finalize(IndexBuffer) hat keine Auswirkungen, weder negativ noch positiv. Komme ich also zu meinen letzten drei Fragen:

4.) wo gehört Finalize und glDeleteBuffers hin?
5.) gldrawelements funktioniert auch mit
Code:
  1. glDrawElements(GL_TRIANGLES, model.IndexCount,GL_UNSIGNED_int,@model.VBOBuffer[0].vertex);
statt mit "nil" hihten... was ist denn besser bzw richtig? Traude schreibt ja, es müsse nil sein und würde für andere Zwecke gebraucht..

und die letzte und brennendste Frage:
6.) Ist jemand was aufgefallen warum hier NVIDIA kotzt?

wäre echt super, wenn sich jemand das alles mal durchlesen könnte und die ein oder andere Frage beantworten könnte - sorry das es etwas lang geraten ist.

Gruß

Wolfgang


Zuletzt geändert von Wölfchen am Mi Apr 03, 2013 18:35, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 19:37 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
Also... (*atem hol, wasser trink, vorbereiten auf große rede ^^*)

Der FillChar-Befehl Zeile 10 scheint model.VBOBuffer mit dem Char #0 zu befüllen (keine ahnung warum..)

Zeile 19/27:
Das Erstellt ein (dafür die 1) VBO und schreibt die Id jenes erstellten VBO's in IDVBO

Dasselbe natürlich mit dem IBO.

nächstes:

glVertexPointer "zeigt" OpenGL wo die Daten sind. Der erste Parameter (die drei) sagt OGL wie viele Elemente ein Vertex hat (xyz), der zweite gibt den Typ an, der dritte gibt den sg. stride an. Das ist der Abstand zwischen zwei vertices, bsp:

Vertex1 1 Float (für iwas anderes) Vertex2

Da wäre das dann ein Stride von 1 - du hast da eben die Normalen zwischen...=> Stride von SizeOf(TVector), so groß ist schl. eine Normale

Der letzte Parameter ist ein Zeiger auf die Vertexdaten im Hauptspeicher, der allerdings nur bei VA's gebraucht wird => NIL bei VBO's

Bei glNormalPointer gibt man nur an wo die Normalen sind, man sagt nicht wie viele Elemente die haben, denn das ist vorgegeben (3).

Finalize sendet *glaub ich* die Daten an die Graka - probiere es einfach mal ohne Finalize => lösch es, bei mir klappts auch ohne ^^

glDeleteBuffers löscht den Buffer => Ins OnClose Event und NICHT in die Renderschleife, denn wenn es das zweite mal in der Renderschleife aufgerufen wird, gibt es logischerweise Access Violation, da die Daten schon gekillt wurden!

glDrawElements muss nil hinten sein, das andere wäre wieder für VA's, wo die Daten nicht auf der Graka liegen, sondern im Hauptspeicher.. (das wäre auch meine NVIDIA-Kotz vermutung...)

EDIT:

nimm einfach mal statt Finalize(VBOBuffer); nur Finalize;

(ich verwende sonst immer glSwapBuffers; das kannste auch probieren?)

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Zuletzt geändert von end am Di Apr 02, 2013 19:48, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 19:44 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
erstmal vielen Dank für die schnelle Antwort!
end hat geschrieben:
Finalize sendet *glaub ich* die Daten an die Graka - probiere es einfach mal ohne Finalize => lösch es, bei mir klappts auch ohne ^^
Wie schon geschrieben, das habe ich probiert, ohne finalze des VBO's geht nix...

end hat geschrieben:
glDrawElements muss nil hinten sein, das andere wäre wieder für VA's, wo die Daten nicht auf der Graka liegen, sondern im Hauptspeicher.. (das wäre auch meine NVIDIA-Kotz vermutung...)

hmm ich dachte das hier wäre dann ein pointer in den VRAM: @model.VBOBuffer[0].vertex oder geht sowas nicht?

jedenfalls kann deine kotz vermutung nicht stimmen, denn mit nil kam ja die Zugriffsverletzung, weitere Ideen?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 19:49 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
nein geht nicht und vorsicht habe eben noch editiert!

(bzgl. STRIDE)

Mal schauen - iwo hatte ich noch eine komplett fehlerfrei, funktionierende VBO-Testimplementation rumliegen...

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Zuletzt geändert von end am Di Apr 02, 2013 19:59, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 19:58 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
end hat geschrieben:

nimm einfach mal statt Finalize(VBOBuffer); nur Finalize;

(ich verwende sonst immer glSwapBuffers; das kannste auch probieren?)


nur finalize geht nicht:
Zitat:
E2029 '(' erwartet, aber ';' gefunden


swapbuffers kommt bei mir später noch... trotzdem geht ohn Finalize(model.VBOBuffer); nix


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 19:59 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
swapbuffers müsste iwo finalize entsprechen, glaub ich zm.

ich empfehle dir mal (so habe ich es iwann mal gelernt ^^):

http://www.songho.ca/opengl/gl_vertexarray.html
http://www.songho.ca/opengl/gl_vbo.html

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 20:40 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
ich hab jetzt in meiner model klasse nen destructor eingebaut:

Code:
  1. destructor Tctb3d.Destroy;
  2. begin
  3.   glDeleteBuffers(1,@IDVbo);
  4.   glDeleteBuffers(1,@IDIndex);
  5.   inherited Destroy;
  6. end;


die links oben schau ich mir auch mal bei gelegenheit an... sonst noch irgendeine idee warum das bei NVIDIA zugriffe verletzt?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 20:52 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
end hat geschrieben:
swapbuffers müsste iwo finalize entsprechen, glaub ich zm.

Vorsicht! Du verwechselst da was. Finalize ist eine Delphifunktion mit der man dynamisch belegten Speicher wieder freigibt, das hat mit OpenGL nichts zu tun.

Passend dazu auch das FillChar mit #0. Hier wird halt der Speicher den man später befüllt komplett mit Nullen vorbelegt. Muss man nicht machen, hilft aber z.B. beim Debuggen o.ä.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Apr 02, 2013 21:25 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Sascha Willems hat geschrieben:
end hat geschrieben:
swapbuffers müsste iwo finalize entsprechen, glaub ich zm.

Vorsicht! Du verwechselst da was. Finalize ist eine Delphifunktion mit der man dynamisch belegten Speicher wieder freigibt, das hat mit OpenGL nichts zu tun.


Hallo Sascha, aber irgendwas scheint es ja zu bewirken, denn wenn ich es weglasse sehe ich kein einziges dreieck...


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Apr 03, 2013 06:20 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Guten Morgen,

Es gibt ne gute und zwei schlechte Nachrichten..

also die gute Nachricht zuerst, es läuft nun auch auf NVIDIA..
die erste schlechte Nachricht ist, ich weiß nicht wieso :shock:

bzw eigentlich gibt es nur 2 Möglichkeiten, die eine ist, es lag doch am nil in glDrawElements die zweite wäre es lag an einem Aufruf im Anschluss an gl_DrawElements, der noch auf Array Basis was zeichnen sollte... ATI hat mir damit Linien kreuz und Quer über den Bildschirm geschossen (sah lustig aus) aber weils keinen Fehler angezeigt hat, hab ichs erstmal ignoriert...
Vermutlich war NVIDIA damit weniger glücklich. Ich werd das morgen nochmal explizit testen und ne Version machen wo ich nur das wieder einschalte.

Jetzt zur eigentlichen schlechten Nachricht...

Ja es läuft, aber - die Graka hier hat etwas weniger VRAM als die ATI zuhaus und offenbar passt mein 800MB beispiel nicht rein.. was zur Folge hat das die Anwendung erst flackert, dann "Keine Rückmeldung" produziert und danach liefert OpenGL den Error "nicht genügend Arbeitsspeicher".

Ich hatte ja die stille Hoffnung das er dann zurück in den RAM auslagert, aber das scheint "von selbst" nicht zu passieren..
Jetzt die Frage: Gibts nen Trick um ihm "Einfach" zu sagen so nach dem Motto "if OpenglError = Nicht genügend Arbeitsspeicher then do begin lager die VBO's in arrays aus und render die.."
Oder hat jemand ne Idee wie ich sowas implementieren könnte?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Apr 03, 2013 10:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Das Auslagern eines VBOs in den Arbeitsspeicher geht genauso wie bei Texturen automatisiert über den Treiber, da hast du also keinen Einfluss drauf. Handelt es sich um ein einzelnes VBO? Wenn ja, dann teil dass mal in Häppchen auf, afaik kann man ein riesiges VBO nicht teilweise im VRAM und RAM lagern.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Apr 03, 2013 12:59 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
nein es sind insgesamt 398 VBO's bei dem beispiel. Der Bildschirm zeigt kurz "no signal" dann meldet sich windows wieder, sagt Keine Rückmeldung bei meiner Anwendung und wenn ich sag "Auf Antwort des Programms warten" dann gibt mir OpenGL zu wenig Arbeitsspeicher zurück
...

übrigens hab ich auf ner NVIDIA Quadro 2000 jetzt doch noch Zugriffsverletzungen, auf der Quadro FX 1800 hier läuft es...
*seufz* scheint als sei die neue Generation NVIDIA noch empfindlicher


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Apr 05, 2013 10:16 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Hat irgendjemand noch ne idee was ich bei einer Quadro 2000 von NVIDIA anders machen muß?

Ich verzweifel hier noch, Meine Anwendung läuft fehlerfrei auf 2 ATI Grakas und einer NVIDIA 1800 FX aber stürzt sofort ab bei NVIDIA Quadro 2000...

Fehlermeldung ist erst nicht lesbar (leeres fenster) wenn mans 10x wegklickt steht irgendwann drin "Zugriffsverletzung bei..."


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Apr 05, 2013 11:01 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Welchen Fehler wirft dir dort denn OpenGL (glGetError)? Wenn das nichts bringt, dann versuchs mal mit dem gDEBugger zu debuggen, der leistet da oft hilfreiche Dienste.

Ansonsten sollten VBOs auch auf der Quadro gehen. Die werden ja von allen modernen 3D-Anwendungen genutzt, und auch bei meinen Spielen und Demoss weiss ich dass die mit VBOs auch auf Quadrokarten laufen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Apr 05, 2013 12:00 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Die Anwendung stürzt sofort ab, ich bekomme keine chance glgeterror zu lesen... ich werd mal versuchen es in ein textfile zu schreiben.. bisher geht das in den fenster caption, vielleicht steht ja doch was drin

Ja die Quadro 2000 muß VBO's können, aber irgendwas schmeckt ihr nicht an meiner Version..

ich hab mir jetzt nen Laptop gekrallt der hier rumsteht da ist ne Quadro 1000M drin, die das gleiche verhalten aufzeigt also werd ich am Wochenende gelegenheit haben damit zu testen..


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 27 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.632s | 17 Queries | GZIP : On ]