Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

n0_0ne

1x Contest-Sieger

  • »n0_0ne« ist der Autor dieses Themas
  • Private Nachricht senden

1

07.10.2010, 23:45

Probleme mit Vertex Buffer Objects

Hi,

Ich bin gerade dabei mal die vertex buffer objects in meinem programm zu implementieren, allerdings kann ich meinen code nicht wirklich testen, da das programm bereits bei

C-/C++-Quelltext

1
2
GLuint test;
glGenBuffersARB(1, &test);

abstürzt... dummerweise funktioniert mein debugger zur zeit auch nicht, aber ich denke der würde mir hier auch nicht so wirklich weiterhelfen.

Da man bei der funktion ja nicht wirklich was falsch machen kann, muss mit ihr selbst irgendwas nicht stimmen. Ich verwende GLEW um zu testen, ob die extension unterstützt wird und die funktionen passend zu "laden", aber irgendwie bin ich etwas verwirrt...

if (GLEW_ARB_vertex_buffer_object) liefert false
if (glewGetExtension("GL_ARB_vertex_buffer_object")) liefert true
if (GL_ARB_vertex_buffer_object) liefert true (wobei das glaub ich was internes von glew ist und immer true ist)
if (glewIsSupported(GL_ARB_vertex_buffer_object")) liefert false
dem kommandozeilentool glewinfo nach, wird GL_ARB_vertex_buffer_object und alle dazugehörungen funktionen unterstützt

Ihr seht schon, irgendwie widerspricht sich hier einiges, irgendwas läuft wohl schief... muss ich außer einem glewInit() noch irgendwas besonderes machen?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »n0_0ne« (09.10.2010, 11:33)


2

08.10.2010, 00:37

Erscheint komisch,
warum verwendest du nicht einfach glGenVertexArrays() ?

3

08.10.2010, 00:40

Jo, ich verwende auch immer die Versionen ohne ARB. Wobei theoretisch ja beides gehen sollte, die mit ARB sind halt in früheren Ogl Versionen als Extension verfügbar, bevor die dann hinterher ohne ARB zum Standard gehören.
Ansonsten checkst du auch den RÜckgabewert von glewInit?
Lieber dumm fragen, als dumm bleiben!

n0_0ne

1x Contest-Sieger

  • »n0_0ne« ist der Autor dieses Themas
  • Private Nachricht senden

4

08.10.2010, 09:09

hm, also vertex arrays verwende ich bereits, aber der vorteil von VBOs ist ja, dass sie im speicher der grafikkarte liegen, also nicht jedes mal neu übertragen werden müssen (oder macht glGenVertexArrays das auch? kannte ich noch nicht). Und was genau es mit diesem ARB so auf sich hat, weiß ich auch nicht :D ist eig. das erste mal, dass ich was benutze, was nicht OpenGL 1.1 ist ^^
Und ich habe tatsächlich nicht den rückgabewert geprüft, da ich nicht gedacht hätte, dass da was schief laufen kann ^^ tuts aber anscheinend doch:
Error: Missing GL Version

Habe dann danach gegoogled und rausgefunden, dass wohl noch kein OpenGL context erstellt wurde. Da ich Qt benutze und QGLWidget verwende, wußte ich nicht, wann genau der erstellt wird. Bin davon ausgegangen, dass es wohl der Fall sein wird, nachdem das QGLWidget erzeugt wurde, aber dem war wohl nicht so ^^

Hab glewInit jetzt einfach auf den spätest möglichen zeitpunkt verschoben und es hat auf anhieb funktioniert :)

Wäre trotzdem nett, wenn ihr mir noch kurz erklären könntet, was es mit dem ARB auf sich hat und glGenVertexArrays().

PS: 500 Beiträge, yay :D

EDIT: hhmm, ich habe mal die performance verglichen zwischen den normalen vertexarrays, die ich jeden frame neu verschicke und dem vbo, wo ichs nur 1x mache... 0 unterschied, wie kann das sein?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »n0_0ne« (08.10.2010, 09:27)


5

08.10.2010, 09:48

ARB heißt Architecture Review Board und befasst sich mit der Standardisierung von Erweiterungen für OpenGL.
Haben Erweiterungen die Endung ARB bekommen kann man eigentlich immer davon ausgeben das sie in einer der darauffolgenden Versionen von OpenGL im Core enthalten sein werden.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

6

08.10.2010, 09:49

Wäre trotzdem nett, wenn ihr mir noch kurz erklären könntet, was es mit dem ARB auf sich hat

Es ist eigentlich so wie schon gesagt wurde. Wenn OpenGL x.y einen gewissen Funktionsumfang hat und man etwas neues hinzufügen will ohne gleich eine neue Version zu veröffentlichen, dann wird das über eine Extension gemacht. Das können Firmen speziell für sich machen, dann gibt es wie früher z.B. Nvidia und ATI spezifische Extensions, oder es wird vom ARB (Architecture Review Board) gemacht. Wenn das ARB Extensions beschließt werden diese halt mit dem ARB suffix gekenntzeichnet und werden nach einer gewissen Probephase dann ohne das ARB in die nächste Version fest eingebaut.

und glGenVertexArrays().

Also laut http://www.opengl.org/wiki/Tutorial2:_VA…s_%28C_/_SDL%29 enthalten die Vertexarrays letztendlich nur VBOs und enthalten nur zusätzliche Informationen wie diese im Shader verwendet werden.

n0_0ne

1x Contest-Sieger

  • »n0_0ne« ist der Autor dieses Themas
  • Private Nachricht senden

7

08.10.2010, 22:14

Also ich denke es gibt hier etwas durcheinander, was die namen der dinge angeht ^^

Meiner meinung nach habt ihr hiervon gesprochen (was ich noch nicht kannte)
http://74.54.224.213/wiki/Vertex_Array_Object
und ich davon:
http://74.54.224.213/wiki/Vertex_Arrays
http://74.54.224.213/wiki/Vertex_Buffer_Object

Zitat: Before VBOs, there was plain old vertex arrays. This means that your vertices and vertex attributes and indices are in RAM.
Of course, this doesn't give the best performance since every time you want GL to draw, the driver has to upload the vertices to the GPU.

Aus dem Grund wollte ich auf VBOs umsteigen, weil ich mir da doch einen geschwindigkeitsschub erhofft habe. Ich habe mir einfach mal einen sehr detaillierten Torus erstellt, dessen Daten (vertexdaten wie positionen, normalen, texturcoords, sowie indizes der einzelnen triangles) sich auf ziemlich genau 100MB belaufen.

Wenn ich alles im immediate mode rendere (also glBegin etc) komme ich auf etwa 3 FPS, mit meinen Vertex Arrays, die zwar immer noch in jedem Frame 100MB zur Graka schieben müssen komme ich auf 6FPS. Ich dachte mir jetzt, dass es doch wohl einen unterschied machen muss, ob man 100MB daten zur graka schickt in jedem frame oder nicht. Aber anscheinend ist das nicht der fall, denn wenn ich mit meinen VBOs rendern lasse (d.h. 1x die daten übertrage und dann immer nur wieder verwende), komme ich wie vorher auf 6FPS.

Ich verstehe nicht, wieso sich das nicht bemerkbar macht, wenn die datenübertragung so schnell ist, dass es überhaupt keinen unterschied macht, wofür gibt es dann überhaupt VBOs? einfach nur um den normalen arbeitsspeicher zu entlasten, weil man ja die daten jetzt im GPU RAM hat, und aus dem normalen löschen kann?

EDIT: Ich hab das ganze jetzt mal mit vielen einzelnen objekten, statt einem komplexen getestet und es stellt sich raus, dass ich mit den vertex arrays 15 FPS schaffe, mit den VBOs grade mal 3-5 FPS... wie kann das sein ^^ was kann man denn da falsch machen o_O

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »n0_0ne« (08.10.2010, 22:27)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

08.10.2010, 23:10

Ich kann dir sagen dass du etwas falsch machst aber mangels weiterer Information leider nicht mehr. Beschreib halt mal was genau du machst...

9

09.10.2010, 02:03

jupp da is definitive was falsch, was genau machst du eigentlich?

n0_0ne

1x Contest-Sieger

  • »n0_0ne« ist der Autor dieses Themas
  • Private Nachricht senden

10

09.10.2010, 11:32

Nunja, es ist noch nichts besonderes. Ich versuche nur mich ein bisschen in OpenGL einzuarbeiten. Man könnte sagen ich programmiere eine Art Partikelsystem, nur mit 3D-Objekten als Partikel, z.B. Cube, Torus, Sphere, Cylinder, Frustum etc. Cube sind nunmal Cubes, aber beim Torus z.B. kann man den Detailgrad einstellen, sodass man da auch schonmal nen Torus von 100MB Daten generieren lassen kann. :)
Der Normalfall sollte aber eben sein, dass man sehr viele relativ einfache Objekte hat, also Cubes, Octahedrons aber auch Spheres mit relativ niedriger Detailstufe.

Vielleicht poste ich mal den meiner meinung nach relevanten Code.

Die Vertex-Struktur:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Vertex {
    Vertex(double x, double y, double z, double a = 0.0f, double b = 1.0f, double c = 0.0f, double textureX = 0.0f, double textureY = 0.0f) {
        pos = Vec4(x, y, z);
        normal = Vec4(a, b, c, 0.0f);
        normal.normalize();
        texture[0] = textureX;
        texture[1] = textureY;
    }

    Vec4 pos;
    Vec4 normal;
    double texture[2];
};


Vec4 hat eigentlich nur ein double-array der größe 4 und einige hilfsfunktionen (z.B. normalize)

Jetzt der code fürs Rendern, steckt in der Class RenderObject, von der alle Objekte (wie z.B. Torus) erben. Haben alle einen vector mit den vertices und einen vector mit den indizes der vertices für die einzelnen triangles (Faces).

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
        if (firstTime) {
            // VertexVBO
            glGenBuffersARB(1, &vertexVBO);
            glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexVBO);
            // allocate memory
            glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(Vertex)*m_vertexArray.size(), NULL, GL_STATIC_DRAW_ARB);
            // transfer data
            glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(Vertex)*m_vertexArray.size(), &(m_vertexArray[0].pos[0]));

            // set pointer to vertex, normal and texturecoords arrays (inside the VBO)
            glVertexPointer(4, GL_DOUBLE, sizeof(Vertex), 0);
            glNormalPointer(GL_DOUBLE, sizeof(Vertex), BUFFER_OFFSET(sizeof(Vec4)));
            glTexCoordPointer(2, GL_DOUBLE, sizeof(Vertex), BUFFER_OFFSET(2*sizeof(Vec4)));

            // IndexVBO
            glGenBuffersARB(1, &indexVBO);
            glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexVBO);
            glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(Face)*m_faceArray.size(), NULL, GL_STATIC_DRAW_ARB);
            glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(Face)*m_faceArray.size(), &(m_faceArray[0].i1));

            firstTime = false;
        }

        // bind vertex and index VBO
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexVBO);
        glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexVBO);

        // activate and specify pointer to arrays
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        // draw triangles
        glDrawElements(GL_TRIANGLES, m_faceArray.size()*3, GL_UNSIGNED_INT, BUFFER_OFFSET(0));

        // deactivate arrays after drawing
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        // it is good idea to release VBOs with ID 0 after use.
        // Once bound with 0, all pointers in gl*Pointer() behave as real
        // pointer, so, normal vertex array operations are re-activated
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);


Man sieht schon, dass zur zeit noch jedes objekt seine eigenen VBOs hat, auch wenn das eigentlich nicht nötig wäre, da ja jeder Cube eigentlich das selbe benutzen könnte, aber dazu muss ich dann noch einiges umschreiben.

Wäre für Hinweise wirklich dankbar :) Falls euch zum Verständnis noch irgendwas fehlt, einfach fragen ^^

Werbeanzeige