Dip beim Verbinden von geblendeten Antialiaslinien

9

Ich habe ein Problem, wenn ich zwei Antialias-Linien bei der Verwendung eines Mischmodus einsetze, bekomme ich einen Sprung an dem Punkt, an dem sie sich verbinden. Mit dem Mischmodus meine ich, dass ich meine Antialias-Linie zeichne, indem ich das Verhältnis von Linienfarbe zu Hintergrundfarbe berechne. Wenn das Verhältnis für ein Pixel beispielsweise 70% ist, ist das neue Pixel 0,7 * Linienfarbe + 0,3 * Hintergrundfarbe. Meine Antialiasing-Funktion für Zeilen besteht im Wesentlichen aus einer Fehlerfunktion (obwohl ich annehme, dass das gleiche Problem für die meisten Antialiasing-Funktionen auftritt), wie folgt:

Wenn also zwei Linien aufeinander treffen, eine nach der anderen, kommt es zu einem Einbruch, die Nahtstelle der beiden Linien sinkt auf 75% der Intensität, an der sie liegen sollte, weil zu diesem Zeitpunkt 50% des Hintergrunds für die erste Zeile und dann 50% dieser 50% blieben nach dem Zeichnen der zweiten Zeile, wenn 0% übrig bleiben sollten:

Ich kann nur annehmen, dass es ein übliches Problem ist, Antialiasing-Rastergrafiken mit verbundenen Linien zu zeichnen, also muss es eine gemeinsame Lösung haben, aber ich habe keine Ahnung, was das ist. Danke!

Auch: Um klar zu machen, wie die Linien gezeichnet werden, werden die Linien in der Breite mit einer Gauß-Funktion (e ^ -x * x) versehen und beide Enden werden mit einem erhöhten Fehler abgerundet Funktionen. Sie können ein Beispiel dafür sehen, wie eine 10 px lange horizontale Linie aussieht, indem Sie in WolframAlpha '0.5erfc (-x-5) * 0.5erfc (x-5) * e ^ (-y * y)' eingeben.

    
Michel Rouzic 16.09.2012, 12:58
quelle

4 Antworten

0

Irgendwann habe ich die Antwort auf dieses Problem gefunden. Es gibt keinen vernünftigen Weg, dies zu tun, indem Sie direkt eine Linie nach der anderen direkt auf das Hauptbild zeichnen, weil Sie nicht möchten, dass die Linien miteinander vermischt werden, Sie wollen, dass sie zusammen addiert werden und dann das Ergebnis dieser Summe von Linien haben in das Hauptbild eingefügt.

Allerdings ist das unhandlich, wenn Sie alle diese Zeilen in einen separaten Puffer zeichnen müssen und dann diesen ganzen Puffer in den Hauptpuffer migrieren müssen, was ich als ungeeignet ansah und ablehnte, bevor ich diese Frage stellte. Zum Glück habe ich meine Vorgehensweise geändert, anstatt einen Puffer zu haben, auf dem Element für Element gezeichnet wird, verwende ich einen Ansatz pro Pixel, bei dem jedes Pixel direkt berechnet wird, indem man eine Liste von Elementen durchgeht, um es zu zeichnen der Parallelisierung (mit OpenCL). Anstatt also zusätzliche Puffer zu verwenden, brauche ich einfach ein kleines Array, das ein paar zusätzliche Pixelwerte enthalten kann, und in meiner Liste der zu zeichnenden Elemente habe ich Elemente, die als Klammern dienen, also zum Beispiel statt:

image => (blend) line1 => (blend) line2 => (blend) line3

Ich kann haben:

image => (blend) [0 => (add) line1 => (add) line2 => (add) line3]

Dies geschieht, indem Sie die Verwendung eines einzelnen Pixelwerts durch ein Array von Werten für jede Tiefe der Klammern ersetzen. In diesem Fall haben Sie also bei v[0] das Pixel von image Beginne mit v[1] bei 0 und füge jede Zeile hinzu, und wenn alle Zeilen hinzugefügt sind, würde das Schließen der Klammer v[1] in v[0] einfügen und der korrekte resultierende Pixelwert wäre da.

Also das ist es, es ist ziemlich einfach, es ist nur ein Problem, wenn Sie sich nicht erlauben, das Äquivalent einer Gruppe von Ebenen in Photoshop zu verwenden.

    
Michel Rouzic 21.05.2016, 13:09
quelle
1

Schön aussehende kontinuierliche Linien, die aus gemischten Segmenten zusammengesetzt sind, werden im Allgemeinen nicht möglich sein, wenn Sie sie als Segmente betrachten - wenn Sie nur an den Fall denken, eine Linie zu haben und dann das nächste Segment entweder gleichzeitig zu zeichnen Winkel und dann in einem 90-Grad-Winkel. Die Pixelfarben für eine Linie hängen vom Winkel ab, den sie mit der nächsten Linie verbindet

Was Sie dann denken müssen, sind Segmente mit abgewinkelten Enden.

Um es zu zeichnen, suchen Sie nach Literatur über die Gehrung von Fasenliniejoin (Gehrung ist wahrscheinlich einfacher).

    
tjltjl 25.12.2012 23:04
quelle
0

Wenn Sie die angrenzenden Linien mit Blending zeichnen, ist das ein ziemlich unmögliches Problem.

Eine gute Möglichkeit, darüber nachzudenken, ist eine Abstandsfunktion zu einer idealen Form. Eine Pixelintensität bildet (über eine Funktion) den Abstand zur Form ab. Mit zwei perfekten Linien wäre das nur das Minimum.

Das bedeutet leider, dass Sie die Entfernung zu jeder Zeile benötigen, die einen Pixel beeinflussen könnte. Dies ist, was einige Text Rasterizer tun.

Alternativ gewicht man keine Linien. Sie sind entweder ein- oder ausgeschaltet pro Pixel. Dann lassen Sie Super-Sampling den Rest erledigen. Das ist, was Software-Vektor-Renderer wie Flash oder Svg machen.

    
starmole 04.02.2013 08:01
quelle
0

Die Idee von thang könnte ein guter Ausgangspunkt sein: Kurz gesagt, um das Zentrum des "Pinsels" zu steuern der Kanten. Im Idealfall mit schönen runden Endpunkten würden Sie bei diesem Ansatz schöne runde Ecken sehen.

Die Wahrheit wird jedoch nicht so schön sein. Das Problem besteht darin, dass Sie zunächst eine Linie mit Ihrer Zielfläche vermischen und dann die zweite Linie auf der Fläche, auf der bereits eine Linie "eingebrannt" ist, mit Alpha überblenden. Das Endergebnis wäre ein fetterer Blob an der Ecke, wo zwei durchscheinende Pixel blit übereinander liegen (Sie können diesen Effekt in Wirklichkeit beobachten, wenn Sie beispielsweise versuchen, Verbindungsliniensegmente in Gimp zu zeichnen).

Ich denke, das kann man nicht umgehen, wenn man bei dieser Einstellung diese einfache einzeilige Methode verwendet (man müsste also in die Richtung anderer vorgeschlagener Antworten gehen, indem man Polylinien-Algorithmen oder Super-Sampling verwendet). Abhängig von Ihren Zielen haben Sie jedoch möglicherweise eine praktikable Lösung.

Dies bedeutet, dass Sie Ihr Grafikobjekt auf eine separate Oberfläche mit Alpha vorrendern. Hier können Sie die Alphas der einzelnen Linien kombinieren (z. B. den größten Wert aus dem Zielpixel und dem aufgetragenen Pixel nehmen), um das gewünschte Ergebnis zu erzielen (keine fetten Kleckse an den Ecken).

Der Nachteil ist, dass Sie eine separate Oberfläche benötigen, die Sie auf Ihrem Ziel blitten müssen, wenn das Objekt vollständig ist: Dies benötigt sowohl zusätzlichen Speicher als auch Verarbeitungszeit.

Sie können dies umgehen, wenn Sie nur ein flacher (einfarbiges) Ziel rendern müssen: Sie müssen dann einfach nicht die richtige Alpha-Mischung durchführen und können die kombinierten Alpha-Berechnungen an Ort und Stelle durchführen. Diese Lösung kann praktikabel sein, wenn der Hintergrund leicht berechnet werden kann (wie zum Beispiel ein Koordinatenraster), also insgesamt, wenn Sie leicht den ursprünglichen Pixelwert des Hintergrunds erhalten und Sie in der Lage sind, dagegen zu kombinieren (das wird auch funktionieren) Wenn du den Hintergrund, über den du rendest, in einer separaten Oberfläche behältst, dann hast du wieder eine andere Oberfläche im Speicher, also hat wahrscheinlich nichts gewonnen.)

Wenn Ihr Problem von anderer Art ist, kann es auch funktionieren, wenn Sie diese gerenderten Oberflächen beibehalten, dh Sie im Wesentlichen Ihre Linienobjekte vorrendern und sie später nur als Texturen oder Kacheln verwenden.

    
Jubatian 05.07.2013 18:46
quelle