OpenGL und Vertex infos



  • hi,

    eine sache interessiert mich schon lange.

    Wie organisiere ich die Vertexinformationen am besten? Im Normalfall habe ich nen array/vector mit unzähligen vertex info im format[V1x | V1y | V1z | V2x | V2y | V2z |....]

    diese übergebe ich ja dann an die Graka mit glVertex, Buffer objects oder was weiß ich..

    die ist sicher einfach wenn man keine großen algorithmen über die vertex daten laufen lässt. tut man es doch ist es etwas anstregend sich darüber gedanken zu machen, welchen wert man adieren muss um vom vertex x die z koordinate mit dem vertex y die x koordinate mit vertex z die y koordinate uz addieren..blabla auch das sortieren ist in dieser form etwas trickreicher.

    mich interesseirt nun ob es zb. möglich ist zb. nen struct/classe zu nehmen

    struct {
     float x,y,z;
    }
    

    dieses dann in ein array/vector zu stopfen und dann dieses direkt an opengl zu übergeben und davor natürlich noch den pointer von struct/class auf pointer auf float zu casten?!

    versteht ihr wie ich das meine?
    wenn es mit struct geht, funzt das auch mit klassen?
    vorraussetzung dafür ist natürlich das das struct bzw. die klasse keinen overhead haben. was ich mir bei dem obigen struct noch vorstellen kann. bei klassen vermute ich das es nicht geht..

    hat jemand gedanken dazu?

    ps:bin heute verwirrt, hab 4 stunden gepennt und lerne grad theoretische informatik...



  • kurz gesagt: ja, sofern dein compiler kein ungewoehnliches alignment einfuegt (sowohl struct als auch class)



  • naja, also bei 32bit floats sollte das ja absolut kein problem sein..außer ich kauf mir ne 64bit cpu...



  • naja, standard-alignment ist ja 4 byte - aber kann ja auch beliebig anders eingestellt werden...

    uebliche vertex-strukturen sehen ungefaehr so aus:

    struct Vertex
    {
      float x,y,z; // position
      float nx,ny,nz; // normale
      unsigned char a,b,g,r; // farbe - setzt alignment 1 voraus
      float u,v;             // texture koordinate
    };
    

    ...kann aber zb genausogut aus klassen bestehen, die die entsprechenden teilparameter als member haben und darauf weitere funktionalitaet anbieten:

    struct Vertex
    {
      Vector position;
      Vector normal;
      Color  color;
      UV     uv;
    };
    

    bei opengl koennen die einzelnen komponenten auch aus unterschiedlichen arrays kommen.
    also mach's wie's dir gefaellt...



  • ja das ist klar wie so nen struct aussehen könnte..mich interessiert aber ob ich das immer noch direkt an opengl übergeben kann wenn ich zb.

    std::vector< Vertex > vertexvec;
    

    habe. kann ich dann immer noch sagen

    glVertex3fv( &*(vertexvec.begin()) );
    

    wenn wir davon ausgehen das

    struct Vertex{
    float x,y,z;
    }
    

    ?
    das ist meine frage



  • glVertex3fv( &*(vertexvec.begin()) );
    

    prinzipiell ja, die auswertung des iterators liefert dir ja wieder "Vertex"

    elleganter waere:

    glVertexPointer(3, GL_FLOAT, 0, vertexvec.data());
    


  • vertexvec.data() ? wo kommt das denn her?
    der standard vector hat sowas nicht...



  • Pseudocode schätze ich mal?

    http://www.khronos.org/opengles/documentation/opengles1_0/html/glVertexPointer.html
    Für dich ist stride und eben der Pointer auf das erste Element interessant.



  • pseudocode wenn ich oben std::vector< > nehme?
    egal, vergessen wir das

    aber meine frage ist ja beantwortet..danke

    edit: was glVertexPointer() macht weiß ich 🙂



  • data() ? wo kommt das denn her?

    hier



  • mmhh, ist das nun standard konform oder nicht?
    also vs2005 kennt es nicht und die sgi stl auch nicht...



  • ist das nun standard konform oder nicht?

    sorry fuer die verwirrung - ich benutze primaer die template-klassen aus trolltech's qt und entsprechende funktionalitaet scheint es wohl nur in der gnu-implementierung zu geben.
    darueber hinaus moechtest du wahrscheinlich sowieso in absehbarer zeit vertex-buffer-objects nutzen, die dir effektiv nur einen volatile-void pointer fuer deine daten zur verfuegung stellen, der wegen veraendertem caching-verhalten kein "random access memory" im herkoemmlichen sinne darstellt.
    solang du damit aber nur einmal eine displayliste erstellen willst, bringen dir einzelne glvertex-calls sowieso keine nachteile.
    allerdings vertraust du dann auf die optimierungsfaehigkeiten des treibers, der auf unterschiedlichen karten auch unterschiedliche "ergebnisse" produziert.



  • dann bleib ich einfach bei &*(vertexvec.begin()) 😉

    mmhh, aber warum sollte ich noch ne displaylist erstellen wenn ich sowieso schon die vertex infos in den grafikkartenspeicher geschoben habe?

    , die dir effektiv nur einen volatile-void pointer fuer deine daten zur verfuegung stellen

    kannst du das nochmal bitte ausführen?



  • kannst du das nochmal bitte ausführen?

    die extensions fuer vbo liefern dir speicher im ram deiner grafikkarte.

    da der bus zur grafikkarte allerdings anderem caching-verhalten unterliegt, sollten die daten unbedingt sequentiell geschrieben werden. wenn der compiler aus vermeindlichen optimierungsgruenden die reihenfolge der zu schreibenden vertex-parameter umarrangiert, bekommt man sehr schnell sehr fatale geschwindigkeitseinbussen - daher volatile.

    warum sollte ich noch ne displaylist erstellen wenn ich sowieso schon die vertex infos in den grafikkartenspeicher geschoben habe?

    wie glaubst du das denn erreicht zu haben?
    solang du die vertex-paramter innerhalb eines glbegin-blocks uebertraegst, sammelt der treiber eine gewisse anzahl von polygonen in einem temporaeren buffer, fuehrt nach gutduenken optimierungen darauf aus und schickt jedes mal das ganze ding vom hauptspeicher zur grafikkarte.
    fuer glvertexpointer gilt (ohne vbos) das gleiche, man spart nur ne menge api-calls.
    die einzige moeglichkeit (ohne extensions) die daten permanent im grafikram zu lassen ist eine displayliste.



  • 1. verstanden
    2. da hatte ich wohl was falsch verstanden. ich meinte wenn ich die vertex infos eh schon per vbo übertragen habe machen displaylists keinen sinn mehr. also nutze ich entweder vbos oder displaylists. sehe ich das richtig?

    wobei vbos um einiges dynamischer gehandhabt werden können. bzw. displaylisten absolut statisch sind.



  • wenn ich die vertex infos eh schon per vbo übertragen habe machen displaylists keinen sinn mehr

    richtig - fuer jegliche optimierungen bist du dann aber selber zustaendig


  • Mod

    ConfusedGuy schrieb:

    wobei vbos um einiges dynamischer gehandhabt werden können. bzw. displaylisten absolut statisch sind.

    wobei du weder displaylisten noch VBOs dynamisch fuellen solltest, weil dann der ganze vorteil von denen verfaellt.



  • rapso schrieb:

    wobei du weder displaylisten noch VBOs dynamisch fuellen solltest, weil dann der ganze vorteil von denen verfaellt.

    Dazu zählt dann wahrscheinlich auch verändern, oder ?

    Einfaches Beispiel: Ich muss in meinem Quake 3 Loader noch den Effekt einbauen, dass z.B. Flaggen sich "im Wind bewegen". Eigentlich ist es nur ne Sinus Kurve, die sich entlang der Flagge zieht.
    Wie mache ich das denn am besten? Denn ich wollte eigentlich VBO's endlich mal einbauen um Performance rauszuholen.



  • wobei du weder displaylisten noch VBOs dynamisch fuellen solltest, weil dann der ganze vorteil von denen verfaellt.

    der vorteil von vbos gegenueber displaylisten ist gerade der, dass man die vertexdaten ohne blockierung ueberschreiben kann:
    wird der vertexbuffer "gelockt" waehrend er gerade gerendert wird, generiert der treiber einen neuen buffer und verwirft den alten nach dem rendervorgang. weiterer vorteil ist, dass die einzelnen vertexattribute in unterschiedlichen buffern gehalten werden koennen und man nur die daten ueberschreiben muss, die tatsaechlich von interesse sind.
    das gewuenschte verhalten des buffers kann man dem treiber per GL_STATIC_DRAW_ARB/GL_DYNAMIC_DRAW_ARB beim anlegen mitteilen.
    lesen des buffers sollte man aber auf agp-systemen unbedingt vermeiden, man muss also evtl noch eine lokale kopie der daten im ram halten.

    dass z.B. Flaggen sich "im Wind bewegen".
    Eigentlich ist es nur ne Sinus Kurve, die sich entlang der Flagge zieht.

    dazu benutzt man besser einen vertex-shader der die geometrie bei der transformation entsprechend modifiziert.


  • Mod

    ob mehrere buffer angelegt werden, haengt von gewissen ratings die der treiber fuer buffer vornimmt (z.b. wann der buffer angelegt wird und wie gross er ist und anhand der hints die man uebergibt)

    das

    wird der vertexbuffer "gelockt" waehrend er gerade gerendert wird, generiert der treiber einen neuen buffer und verwirft den alten nach dem rendervorgang.

    ist definitiv nicht der fall, das wuerde den memorymanager ueberlassten. die buffer werden einmal im voraus angelegt und dann bis zum freigeben behalten, ohne user eingriffe werden die buffer nicht geleoscht oder neue buffer angelegt.

    Dazu zählt dann wahrscheinlich auch verändern, oder ?

    veraendern ist sogar noch schlimmer als komplett neu uebertragen. fuer simple dinge nutzt man wie hellihjb schon sagte, shader. und wenn man nicht mit shadern hinkommt, muss man halt mit per cpu die daten neu hochladen, verboten ist es nicht (schliesslich gibt es wohl so ziemlich kein spiel mit nur statischer graphik-geometrie), kostet aber relativ viel renderzeit.


Anmelden zum Antworten