Quadratische Kurve auf GPU zeichnen

9

Meine Aufgabe ist es, eine quadratische Bezier-Kurve (Pfad) über die Stage3d (Adobe Flash) -Technologie zu rendern, die keine Erweiterungen für diese Out-of-the-Box-Erweiterung hat (während OpenGl es, wie ich weiß, hat). Ja, es gibt eine Starling-Extension-Graphics, aber es verwendet eine einfache Methode, um ein Kurvensegment in viele gerade Linien zu unterteilen, was sehr viele Dreiecke für meinen langen Kurvenweg erzeugt.

Also ... Es gibt eine perfekte Möglichkeit, um in der Auflösung unabhängige Formen für Loop und Blinn darzustellen. Ich habe GPUGems3 Artikel gelesen (gpugems3_ch25.html) und portierte diesen Fragment-Shader zu AGAL2:

Quadratischer Pixel-Shader

%Vor%

Es funktioniert. Aber es gibt zwei grundlegende Probleme:

  1. Ich verstehe diesen Algorithmus nicht :(. Ich habe über vorzeichenbehaftete Distanzfelder gelesen, Derivate und andere ... ich habe viele Stunden gedacht und nochmal gelesen - aber kein Ergebnis! Meine Frage ist: Kann mir jemand helfen und erklären, was in diesem Shader passiert (zeilenweise (!), wenn es möglich ist)?

  2. Das zweite Problem ist, dass die Kurve an der Ecke des Dreiecks abgeschnitten ist und eine variable Stärke hat . Bitte sehen Sie sich das Bild an: Ссылка Wenn ich einen Pfad zeichne, sieht das so aus: Ссылка

Ich mag diese Methode, indem ich ein Dreieck pro Kurvensegment verwende, da keine Geometrie benötigt wird. Und ich brauche keine sehr dicken Kurven (1-2 px ist hervorragend), aber eine variable Dicke ist ein Problem. Kann mir jemand helfen?

(Entschuldigung für mein Englisch. Es ist nicht meine Muttersprache.)

[edit1 von Spektre] gerade von Kommentar und ungültiger Antwort verschoben

Ich plane, ein Dreieck pro Kurvensegment zu verwenden, so wie auf dem Bild

  • Der Pfad besteht aus vielen Dreiecken
  • eins pro Pfadsegment (quadratische Kurve)
  • Wie geht man mit diesem Ansatz um, wenn alle Kontrollpunkte kollinear (auf der gleichen Geraden liegen) oder nahezu kollinear verlaufen?
Ilya 10.07.2015, 08:54
quelle

1 Antwort

7

Für 3 Kontrollpunkt-Bezier-Kurven würde ich:

  1. verwende Dreiecke als Primitive
  2. vergrößern Sie die Kontrollpunkte um den Bereich um die Kurve herum, um Artefakte zu vermeiden

Dieser Weg ist schnell und es gibt kein Problem, A',B',C' von A,B,C zu berechnen und umgekehrt. Wenn die Skala konstant ist (zB scale=1.25 ), dann ist die maximal nutzbare Kurve thickness<=2.0*min(|control_point-M|)*(scale-1.0) .

Für eine sicherere Vergrößerung können Sie die exakte Skalierung berechnen (zum Beispiel im Geometrieshader) und sie an den Scheitelpunkt und das Fragment übergeben ... Alle oben genannten Schritte können mit dem Geometrieshader durchgeführt werden. Sie sollten Transparenz verwenden, um die Kurven korrekt miteinander zu verbinden. Der durchschnittliche Mittelpunkt sollte gleich bleiben M=A+B+C=A'+B'+C'

wenn Transparenz keine Option ist

Dann müssen Sie den Ansatz ändern, so dass Sie Kontrollpunkte und Positionen innerhalb von Texturen übergeben.

  1. Erstellen Sie eine 2D float Textur mit Kontrollpunkten

    • etwas wie float pnt[9][N]
    • pnt[0,1,2][] ist Kontrollpunkt A(x,y,z)
    • pnt[3,4,5][] ist Kontrollpunkt B(x,y,z)
    • pnt[6,7,8][] ist Kontrollpunkt C(x,y,z)
  2. erstellt auch 1D-Farbtextur

    • etwas wie rgba col[N]
    • Die x -Achsenauflösung beider Texturen = N ist die Anzahl der Bezier-Kurven
  3. Zeichnen Sie nun ein einzelnes Quad, das den gesamten Bildschirm abdeckt

    Und innerhalb des Fragment-Shaders prüfen, ob Pixel innerhalb einer der Kurven liegt. Wenn ja, gib seine Farbe aus ...

Dies kann bei hoher Bezier-Kurve count N

sehr langsam werden

[edit1] fast kollineare Kontrollpunkte

für diejenigen, die ich Quads verwenden würde

  • D,E sind gespiegelte Punkte A,B around C
  • D=C+C-A
  • E=C+C-B
  • C ist der Mittelpunkt M = (A+B+D+E)/4 = C = (A'+B'+C'+D')/4
  • und A',B',C',D' sind vergrößert A,B,D,E Kontrollpunkte
  • A'=C+(A -C)*scale
  • B'=C+(B -C)*scale
  • A =C+(A'-C)/scale
  • B =C+(B'-C)/scale

Dies kann für jedes Bézier nicht nur fast kollinear verwendet werden, sondern es werden auch größere Polygone verwendet, damit es langsamer wird (mehr Fragmente werden dann wirklich benötigt)

    
Spektre 15.07.2015 06:36
quelle