Transform Feedback + Geometry Shader + Triangles + Recursion: vbo und vto Buffer swap

  • Hallo,


    ich studiere an der Hochschule in Trier und mache ein Projekt, welches ich am 28.02.2017 abgebe.
    Das Projekt ist ein Rekursiver 3D Pythagoras-Baum aus Dreiecken unter verwendung von Transform Feedback und Geometry Shader.
    Mein Problem ist: Ich möchte die beiden Buffer vbo und vto nach einem Transform-Feedback-Schritt tauschen.
    Das Ergebnis des ersten Rekursionsschrittes soll als Eingabe das nächsten Rekursionsschrittes dienen und der Ergebnis soll dann in vbo geschrieben werden. Danach soll wieder getauscht werden. usw.


    Der Code zu meinem Projekt befindet sich am Ende des Threads.


    Ich habe folgenden Thread gefunden:


    https://www.informatik-forum.a…in-Vertex-Buffer-zur%FCck


    Der Thread hat mich auf die Funktionen

    Code
    1. glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tbo);


    und

    Code
    1. glDrawTransformFeedback(GL_TRIANGLES, tbo);


    aufmerksam gemacht. Diese ersetzt anscheinend ab dem zweien Rekursionsschritt die Funktion

    Code
    1. glBufferData(GL_ARRAY_BUFFER, 1000, feedback, GL_STATIC_DRAW);


    bzw.

    Code
    1. glDrawArrays(GL_TRIANGLES, 0, 6);


    Leider führt dies dazu, dass ich im zweiten Rekursionschritt nur noch 0.0-Werte zurück erhalte.
    vbo.vto.swap_2.jpg



    Führe ich das Programm mit

    Code
    1. glBufferData(GL_ARRAY_BUFFER, 1000, feedback, GL_STATIC_DRAW);


    bzw.

    Code
    1. glDrawArrays(GL_TRIANGLES, 0, 6);


    aus, dann erhalte ich erwartungsgemäß 9 Zeilen mit Werten
    vbo.vto.swap_1.jpg




    Jedoch denke ich, dass diese Variante nicht effizient ist, denn soweit ich das verstehe hole ich die Daten hierbei über glGetBufferSubData(...) auf die CPU / RAM zurück und übertrage Sie anschließend mit glBufferData(...) zurück auf die GPU / GRAM zurück.
    Ziel wäre es doch die Buffer auf der GPU / GRAM zu swappen. Leider weiß ich nicht wie das geht.




    Code in Programm kopieren, das Zeilennummern hat.
    Beschreibung:

    Das Programm besteht aus zwei unabhängigen Teilen. Die Teile sind jetzt noch nicht zusammen gebaut, sollen es aber später einmal.


    Der eine Teil ist das procedurale Berechnen des Baumes. Hier zu zählen:

    • vertexShaderProcedural
    • geoShaderProcedural
    • doProceduralComputing()


    Der andere Teil ist ein einfaches Rendering (hierbei wird zu testzwecken das Dreieck verdoppelt mittels GeoShader):

    • vertexShaderSource
    • fragmentShaderSource
    • geometryShaderSource
    • createRenderingShaders()
    • linkRenderingShaders()
    • main()


    Außerdem macht doInitStuff() Vorbereitungen für beide Prozesse.
    Relevant sind hier nur die Dinge für das procedurale Berechnen.
    vertexShaderProcedural:
    Ein klassischer pass-through Shader der nichts macht außer die Daten weiter zu leiten.
    geoShaderProcedural:
    Verarbeitet Triangles und verdoppelt das Dreieck, wenn der "length"-Wert größer 0 ist. (Dies wird später die Funktionalität zum erzeugen des Baumes)
    doProceduralComputing():
    Zeile 245 - 251: Die Daten festlegen die ich auslesen möchte aus dem geoShader.
    Zeile 277 - 282: Die Vertex Daten, die am im ersten Rekursionsschritt in den Vertex-Shader kommen.
    Zeile 284 - 302: VBO Binden und mit Daten befüllen.
    Zeile 308 - 315: TBO Binden und zum Lesen bereitstellen.
    Zeile 326 - 367: Transform Feedback durchführen.
    Zeile 372 - 385: Ergebnis auslesen und anzeigen.
    //Dann kommt der zweite Durchlauf jetzt sollen VBO und TBO einfach nur getauscht werden.
    Zeile 392 - 393: Wie oben angesprochen.
    Zeile 414 - 415: Wie oben angesprochen.

    vbo.vto.swap_1.jpgvbo.vto.swap_2.jpg

  • Also, um es kurz zu machen: Ich denke du brauchst als Setup 2 VBOs und 2 Transform-Feedback-Buffer (TFB). Der erste TFB hängt mit dem ersten VBO zusammen und schreibt dort hinein. Der zweite TFB hängt mit dem zweiten VBO zusammen. Initial haben beide Buffer die selben Daten.


    Dann wird das erste VBO gebindet (glBindBuffer) und der zweite (!) TFB (glBindTransformFeedback) und der erste Rendercall (glBeginTransformFeedback) ausgeführt. Somit steht das Ergebnis im zweiten VBO. In der nächsten Iteration/Rekursion wird dann das zweite VBO gebindet und der erste TFB. Dazwischen wird nichts mit glGetBufferSubData gemacht, sonst ja, wird zwischen GPU und CPU kopiert.


    Beschrieben ist das unter anderem hier: http://ogldev.atspace.co.uk/www/tutorial28/tutorial28.html

    Stefan Spelitz
    [Computergraphik UE Tutor 2017SS]

  • Haha xD
    Genau diesen Artikel hatte ich zwischenzeitlich auch gefunden =)
    Ich versuche mich nachher mal daran, wennauch ich es noch nicht ganz durchblicke, warum das so ist. Wenn ich nur einen einzigen Pipeline-Aufruf habe, dann reichen ja ein vbo und ein tbo. vbo enthält die daten, tbo das ergebnis. Warum das eine vbo auf einmal noch ein dazugehöriges tbo braucht (welches es ja bisher nicht hat) und warum das tbo auf einmal ein dazugehöriges vbo hat (welches es ja bisher nicht hat) verstehe ich nicht.


    Danke - Enomine

  • Das was du tbo nennst ist laut deinem Code aber kein Transform-Feedback-Buffer, sondern ein weiteres VBO (GL_ARRAY_BUFFER). Somit hast du schon mal 2 VBOs, was gut ist, aber sonst stimmt halt nicht so viel mit dem Code. glBindTransformFeedback wird zum Beispiel gar nicht gemacht (ist auskommentiert) ?


    Warum es von allem 2 geben soll, ist weil man nicht in den selben Buffer reinschreibt aus den man rausliest UND zu jedem VBO gibt es hier genau ein TFB, da die TFB nur Mittel zum Zweck sind um überhaupt in VBOs reinschreiben zu können.

    Stefan Spelitz
    [Computergraphik UE Tutor 2017SS]

  • Hey, ich habe 6 Stunden versucht die rekursion zum laufen zu bekommen. Es hat nichts geholfen. Es geht einfach nicht.
    Dann habe ich es iterativ bis zur 4. Stufe implementiert und Abgegeben. Ne 2 wirds trotzdem werden denke ich.


    Danke für die Hilfe.


    capture_01032017_000718_917.pngcapture_01032017_042907_496.pngcapture_01032017_042908_795.pngcapture_01032017_042911_713.png


    Und für alle die in ein paar Jahren kommen hier noch der Code:


    Die Kommentare sind nicht mehr wirklich passent zum Code.


    Benötigt
    glew-2.0.0-win32
    glfw-3.2.1.bin.WIN32
    glm-0.9.8.4