[opengl]vertexarray alternative



  • hi

    da vertex-arrays in opengl ja deprecated sind, was soll ich nutzen um animierte figuren darzustellen? bisher habe ich vbos für statische objekte und vertex-arrays für sich oft ändernde objekte verwendet. nun? können vbos schnell genug daten verändern?



  • Auch VBOs.



  • goat schrieb:

    können vbos schnell genug daten verändern?

    VBOs sind das Einzige was die Grafikkarte wirklich kann. Wenn du Vertex Arrays verwendest dann packt der Treiber die am Ende auch nur in VBOs. Ich denk deine Frage erübrigt sich damit 😉



  • Wichtig ist halt beim senden der Daten GL_STREAM_DRAW als Flag zu übergeben. Dann weiss die Grafikkarte, dass die Daten nur für wenige Frames verwendet werden und kann entsprechend optimieren. GL_STATIC_DRAW wäre das pendant dazu für statische, nicht animierte Objekte.
    HTH



  • Und wie würde das konkret aussehen, wenn die Geometrie sich in jedem Frame ändert?

    Wäre folgendes dann ideal?
    (Wohlgemerkt einen solchen Code-Block pro Material/Textur. Korrekt?)

    GL.BindBuffer(BufferTarget.ArrayBuffer, vad.VBOvertex);
    GL.BufferData(
    	BufferTarget.ArrayBuffer,
        (IntPtr)(vad.vertexArray.Length * sizeof(float)),
        vad.vertexArray,
        BufferUsageHint.StreamDraw);
    GL.VertexPointer(3, VertexPointerType.Float, 0, 0);
    
    GL.BindBuffer(BufferTarget.ArrayBuffer, vad.VBOtexture);
    GL.BufferData(
        BufferTarget.ArrayBuffer,
        (IntPtr)(vad.texCoordArray.Length * sizeof(float)),
        vad.texCoordArray,
        BufferUsageHint.StreamDraw);
    GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, 0); 
    
    GL.BindBuffer(BufferTarget.ArrayBuffer, vad.VBOnormal);
    GL.BufferData(
        BufferTarget.ArrayBuffer,
        (IntPtr)(vad.normalCoordArray.Length * sizeof(float)),
        vad.normalCoordArray,
        BufferUsageHint.StreamDraw);
    GL.NormalPointer(NormalPointerType.Float, 0, 0);
    
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, vad.VBOindex);
    GL.BufferData(
        BufferTarget.ElementArrayBuffer,
        (IntPtr)(vad.indexList.Length * sizeof(uint)),
        vad.indexList,
        BufferUsageHint.StreamDraw);
    GL.DrawElements(BeginMode.Triangles, vad.indexList.Length, DrawElementsType.UnsignedInt, 0);
    

    Ich habe VBOs bisher auch nur für statische Geometrie eingesetzt.



  • Wie meinst du das? Du übergibst ja das Flag bereits. Es ist nur ein Hinweis an den Treiber, mehr nicht. Die Daten bleiben trotzdem im Speicher. Nur die Grafikkarte ist eben darauf vorbereitet, dass diese Daten sich bald ändern könnten. Wie solche Optimierungen auf Treiberseite genau aussehen, kann ich dir nicht sagen. Es ist halt einfach nur etwas was man machen sollte.
    Oder ich hab die letzte Frage jetzt falsch verstanden^^.

    http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml



  • Scorcher24 schrieb:

    Wie meinst du das? Du übergibst ja das Flag bereits.

    Na, meine Frage ist wie man das korrekt im Code umsetzt. Ob obige Aufrufabfolge in jedem Frame und für jedes Material/Textur korrekt ist, wenn man dynamische Geometrie hat.

    Kurz und knapp: Ist das so richtig? Oder gibt es da noch was zu verbessern, optimieren, beschleunigen, etc.. ?



  • Ok, glBufferSubData scheint wohl performanter als glBufferDate zu sein für häufige Updates.

    "When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store."



  • Ich würde die Buffer nur anfangs einmal erzeugen und dann mit glBufferSubData() nurmehr updaten und nicht ständig neue machen. Je nachdem wie groß deine Datenmengen sind ist es evtl. auch empfehlenswert besser mit glMapBuffer() zu arbeiten und vielleicht nicht ein VBO für Position, Texcoords, etc. zu verwenden sondern die Daten interleaved in einem VBO abzulegen.



  • Wobei es für die Performance evtl. von Vorteil ist wenn du bevor du den Buffer updatest einmal glBufferData() mit einem Nullpointer für die Daten aufrufst. Treiber interpretieren das normalerweise so dass dich die Daten die momentan im Buffer sind nichtmehr interessieren und daher keine Synchronisation zwischen GPU und CPU notwendig ist.


Anmelden zum Antworten