OpenGL und Vertex infos



  • 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.



  • ist definitiv nicht der fall, das wuerde den memorymanager ueberlassten

    der "lock"-vorgang eines dynamischen vertexbuffers ist auf jeden fall nicht-blockierend, wie der treiber das intern genau loest weiss ich allerdings nicht - vermutlich ein einfacher doublebuffer-mechanismus.
    im falle von multipass rendering ist fuer komplexere vertex-operationen (bone-deformationen etc) eine cpu-seitige transformation manchmal vorzuziehen; weil sonst jeder vertex mehrmals durch den shader muss...


  • Mod

    hellihjb schrieb:

    der "lock"-vorgang eines dynamischen vertexbuffers ist auf jeden fall nicht-blockierend, wie der treiber das intern genau loest weiss ich allerdings nicht - vermutlich ein einfacher doublebuffer-mechanismus.

    der buffer liegt dann im normalen speicher und wird bei bedarf und falls er gelockt war neu auf die graka kopiert. heist aber auch, dass die graka nicht mehr als ein lock asynchron laufen kann, wenn man den buffer mehrmals pro frame locken wuerde, wuerde es vermutlich sehr langsam werden (die moeglichkeit dass der treiber mehrere buffer anlegt statt nur einem ist natuerlich da).



  • der buffer liegt dann im normalen speicher und wird bei bedarf und falls er gelockt war neu auf die graka kopiert

    genau das duerfte eigentlich nicht der fall sein.
    unter verwendungen der vbos (in bezug auf "WRITE_ONLY"-buffer) schreibst du entweder
    - in den agp-addressierbaren bereich aus dem die vertexdaten beim rendern gestreamt werden (imho bis geforce3 so gewesen)
    - direkt in den grafikspeicher

    was auch offensichtlich wird, wenn man versucht aus dem vertexbuffer zu lesen (schneckenlangsam)
    darum liegen imho die daten nicht im hauptspeicher, werden direkt ins grafikram geschrieben und es finden keine zusaetzlichen kopiervorgaenge statt.


Anmelden zum Antworten