Kantenglättung ist der Fachbegriff für die Beseitigung von gezackten Kanten in Bildern. In Filter Forge können die Kantenglättungs-Einstellungen im Menü Kantenglättung angepasst werden. Da Filter Forge eine Sample-basierte Rendering-Architektur verwendet, wird Kantenglättung durch die Berechnung mehrerer Samples pro Pixel und die Mittelung ihrer RGB-Kanäle implementiert, um die resultierende Pixelfarbe zu erzeugen.
Ein naiver Ansatz für die Kantenglättung bestünde darin, für jedes Pixel der zu rendernden Bitmap mehrere Samples vorzunehmen und dann den Durchschnitt aller zurückgegebenen Abtastfarben zu bilden, um die endgültigen Pixel zu erhalten. Dieser Ansatz ist jedoch unwirksam, wenn das Bild hauptsächlich aus einfarbigen oder glatten Bereichen besteht, was häufig der Fall ist.
Um in solchen Fällen Render-Zeit zu sparen, verwendet Filter Forge einen intelligenten Kantenglättungs-Algorithmus – Seine Komponenten können einfarbige oder glatte Bereiche in ihrer Ausgabe melden, die in ihrem Inneren keine Kantenglättung erfordern, aber an ihren Rändern Kantenglättung benötigen. Diese Bereiche werden als Kantenglättungs-Zonen oder AA-Zonen bezeichnet. Alle Filter Forge-Komponenten melden ihre AA-Zonen an den Renderer. Der Renderer kombiniert die AA-Zonen aller Komponenten zur endgültigen AA-Zonen-Karte und lässt sie durch einen Kantenfindungsalgorithmus laufen, der Pixel markiert, die an den Grenzen zwischen verschiedenen AA-Zonen liegen.
Du kannst die AA-Zonen und AA-Kanten (die Karte der für Kantenglättung markierten Pixel) für jeden Filter in Filter Forge über die Befehle im Untermenü Diagnose anzeigen des Menüs Kantenglättung anzeigen.
Um zu veranschaulichen, wie Kantenglättungs-Zonen funktionieren, verwenden wir ein Skript, das drei sich schneidende einfarbige Kreise auf einem einfarbigen Hintergrund rendert. Dieses Bild wird ohne Kantenglättung dargestellt, daher die gezackten Kanten:

ungeglättetes Bild
Wir wollen natürlich, dass alle Kreiskanten kantengeglättet sind. Um dies zu erreichen, muss unser Skript verschiedene AA-Zonenwerte für jeden einfarbigen Bereich im Bild melden. Das folgende Beispielbild zeigt AA-Zonen, die eine korrekte Kantenglättung für das obige Bild ergeben würde. Das Beispiel zeigt die Zonen als Farben, aber eigentlich werden sie durch ganzzahlige Werte dargestellt – Filter Forge wandelt sie nur für die Visualisierung in Farbe um. Beachte, dass das Skript unterschiedliche AA-Zonen für alle Teilbereiche des Bildes ausgibt – zum Beispiel hat jedes der drei "Blütenblätter" der "Blume" in der Mitte des Bildes einen anderen AA-Zonenwert:

AA Zonen
Die kombinierte Karte der AA-Zonen durchläuft dann einen Kantenfindungsalgorithmus, der Pixel markiert, die an den Kanten zwischen verschiedenen AA-Zonen liegen – diese Pixel erhalten während des Kantenglättung-Rendering-Durchgangs mehrere Samples:

AA Kanten
Das letzte Beispiel unten zeigt das Kantenglättungs-Ergebnis. Beim Rendern dieses Bildes berechnete der Filter Forge-Renderer mehrere Samples nur für die Pixel, die für die Kantenglättung markiert waren (in der obigen AA Kanten-Karte weiß dargestellt), während der Rest der Bildpixel mit einem einzigen Sample pro Pixel berechnet wurde:

kantengeglättetes Ergebnis
In den Komponenten Abbildungs-Skript und Kurven-Skript erfolgt die Zonenberichterstattung durch die Berechnung von AA-Zonen während der Ausführung der Funktion get_sample() des Skripts und die Rückgabe des AA-Zonenwerts als letzten optionalen Rückgabewert – siehe das Skript unten. Hier ist das Skript, das wir zum Rendern der obigen Beispiele verwendet haben:
function prepare()
radius = 0.25
end;
function get_sample(x, y)
local r, g, b, a = 0, 0, 0, 1
local aa_zone = 0
-- Red circle
if (x-0.5)^2 + (y-0.3)^2 < radius^2 then
r = 1
aa_zone = combine_aa_zones(aa_zone, 1)
end
-- Green circle
if (x-0.7)^2 + (y-0.65)^2 < radius^2 then
g = 1
aa_zone = combine_aa_zones(aa_zone, 2)
end
-- Blue circle
if (x-0.3)^2 + (y-0.65)^2 < radius^2 then
b = 1
aa_zone = combine_aa_zones(aa_zone, 3)
end
return r, g, b, a, aa_zone
end;
Schauen wir uns das Skript an, insbesondere die fett markierten Zeilen.
Zunächst erstellen wir eine Variable namens aa_zone und initialisieren sie mit Null. Im weiteren Verlauf der Skriptausführung stellen wir dann fest, ob die Sample-Koordinaten x und y einen bestimmten Kreis treffen, und kombinieren den ursprünglichen aa_zone Wert mit einem neuen Zonenwert den wir diesem Kreis zugewiesen haben. Die Kombination erfolgt durch Aufruf der Funktion combine_aa_zones() mit zwei Zonen als Argumenten.
Unser Beispielskript weist dem Hintergrund den Zonenwert 0 und den roten, grünen bzw. blauen Kreisen die Werte 1, 2 und 3 zu. Die endgültige AA-Zonenkarte wird jedoch aufgrund der Kombination von AA-Zonen in überlappenden Bereichen mehr Zonenwerte enthalten.
Wenn die Skriptausführung die return Anweisung am Ende der Funktion get_sample() erreicht, erhalten wir einen einzelnen Zonenwert, der den Ausführungspfad innerhalb dieses speziellen Aufrufs der Funktion get_sample() des Skripts für bestimmte Sample-Koordinaten widerspiegelt. Wenn die Sample-Koordinaten x und y beispielsweise in den Hintergrundbereich fallen (d. h. keiner der drei if -Operatoren tritt in seinen true Zweig ein), bleibt aa_zone auf 0, dem Wert, den es bei der Initialisierung erhalten hat. Treffen die Sample-Koordinaten jedoch den Überschneidungsbereich zwischen rotem und blauem Kreis, ist der Wert von aa_zone eine Kombination aus 0 (Hintergrund), 1 (roter Kreis) und 3 (blauer Kreis).
Als letzten Rückgabewert geben wir den kumulierten aa_zone Wert aus der Funktion get_sample() des Skripts zurück. Dieser Rückgabewert ist optional, sprich wenn dein Skript keine Kanten enthält, die geglättet werden müssen, kannst du ihn getrost weglassen. Weitere Informationen zu den Rückgabewerten von get_sample() findest du unter: Abbildungs-Skript und Kurven-Skript.
Der wichtigste Punkt dieses Beispielskripts ist, dass du einen eindeutigen AA-Zonen-Wert für jeden einfarbigen oder glatten Bereich zurückgeben solltest, der an seinen Rändern Kantenglättung benötigt. Bestimmte AA-Zonen-Werte spielen keine Rolle, solange sie für verschiedene Bildzonen unterschiedlich sind – du kannst die 0, 1, 2 und 3 im obigen Skript durch beliebige Werte ersetzen, z. B. 42, 111, 2222 bzw. 33333, und das Skript wird trotzdem korrekte Kantenglättung erzeugen. Der Aufruf der Funktion combine_aa_zones() ist nicht erforderlich – du kannst die Zonenwerte mit einer eigenen Formel kombinieren, die so einfach sein kann wie die Addition der Werte. Darüber hinaus ist auch die Zonenkombination selbst nicht zwingend erforderlich – sie ist lediglich eine Möglichkeit, eindeutige AA-Zonenwerte für sich überlappende Bereiche zu erzeugen. Viele Muster benötigen keine Zonenkombination – wenn dein Skript z. B. ein Schachbrettmuster oder einen gebänderten Farbverlauf ausgibt, brauchst du nur unterschiedliche AA-Zonenwerte für jedes Quadrat oder jeden Farbverlauf zurückzugeben.
combine_aa_zones() Funktion
combine_aa_zones() ist lediglich eine Funktion, die zwei ganzzahlige*-Zahlen unter Verwendung ihrer Hashes zu einer dritten ganzzahligen*-Zahl kombiniert. Sie ist in keiner Weise an die Interna von Filter Forge gebunden, so dass ihre Verwendung in Skripten nicht notwendig ist – du kannst sie durch jede andere Funktion oder Formel ersetzen, die zwei Ganzzahl-Werte zu einem einzigen Ganzzahl-Wert kombiniert. Wir haben diese Funktion der Einfachheit halber zur Verfügung gestellt - sie verwendet Hashing, was in reinem Lua schwierig zu implementieren ist, da es keine binären arithmetischen Operationen gibt.
integer3 = combine_aa_zones(integer1, integer2)
Kurven-Skript -Komponenten können auch AA-Zonen-Werte aus ihren Skripten zurückgeben. Da das Konzept der "überlappenden Zonen" im Kontext von Kurven wenig Sinn macht, ist es unwahrscheinlich, dass ein Kurven-Skript die Funktion combine_aa_zones() verwendet – du kannst einfach separate AA-Zonen für lineare oder glatte Segmente der Kurve zurückgeben, wie in diesem Beispiel gezeigt:

Hier ist das Kurven-Skript, das dieses Beispiel implementiert. In diesem Beispiel werden keine AA-Zonen berechnet oder kombiniert, sondern nur als Konstanten (111, 222 und 333) in den entsprechenden Zweigen der if-Anweisung zurückgegeben:
function prepare() left = 0.3 right = 0.7 low = 0.25 high = 0.875 end; function get_sample(x, y, t) if (t < left) then return low, 111 elseif (t < right) then
v = low + (high-low) * (t-left) / (right-left) return v, 222 else return high, 333 end end;
Wenn dein Skript über Abbildungs- oder Kurven-Eingaben verfügt, geben die damit verbundenen Komponenten ihre eigenen AA-Zonen zurück, die in die von deinem Skript erzeugte AA-Zonen-Karte gemischt werden sollten. Zum Glück musst du dies nicht manuell erledigen – Filter Forge kombiniert automatisch die von deinem Skript zurückgegebenen AA-Zonen mit den AA-Zonen, die von den mit Skripteingaben verbundenen Abbildungs- oder Kurven-Komponenten zurückgegeben werden.
Dies geschieht folgendermaßen: Jedes Mal, wenn ein Skript eine Abbildungs- oder Kurven-Eingabe-Sampling-Funktion aufruft, wird der von ihr implizit zurückgegebene AA-Zonen-Wert vom Renderer gespeichert. Wenn die Ausführung der get_sample() -Funktion des Skripts beendet ist, werden die AA-Zonen aller während der Skriptausführung gesampelten Abbildungs- und Kurven-Eingaben mit der AA-Zone kombiniert, die das Skript mit seiner get_sample() -Funktion zurückgibt.
Um die Vorteile des automatischen AA-Zonen-Kombinationsalgorithmus von Filter Forge voll auszuschöpfen, solltest du darauf achten, an welcher Stelle im Skript die Funktionen für das Eingabesampling aufgerufen werden. Betrachte die folgenden beiden Skripte. Beide behmen zwei Abbildungs-Eingaben, A und B, auf, wobei die erste von einem kontrastreichen Perlin-Rauschen und die zweite von Ziegelsteine geliefert wird. Beide Skripte erzeugen das gleiche Bild:

function prepare()
end;
function get_sample(x, y)
if (x+y)/2 < 0.5 then
r1, g1, b1, a1 = get_sample_map(x, y, A)
return r1, g1, b1, a1
else
r2, g2, b2, a2 = get_sample_map(x, y, B)
return r2, g2, b2, a2
end;
end;
Dieses Skript sampelt die Eingaben selektiv ab, abhängig von den Koordinaten x und y. Beachte, dass die AA-Zonen, die von der Eingabe A (kontrastreiches Perlin-Rauschen) zurückgegeben werden, nur im oberen linken Teil des Bildes sichtbar sind, und umgekehrt sind die von der Eingabe B (Ziegelsteine) zurückgegebenen Zonen nur im unteren rechten Teil sichtbar. Das resultierende AA-Kantenmuster stimmt perfekt mit dem oben dargestellten Ergebnis überein:


function prepare() end; function get_sample(x, y) r1, g1, b1, a1 = get_sample_map(x, y, A) r2, g2, b2, a2 = get_sample_map(x, y, B) if (x+y)/2 < 0.5 then return r1, g1, b1, a1 else return r2, g2, b2, a2 end; end;
In diesem Skript werden immer beide Eingänge A und B gesampelt, wobei die Sample-Koordinaten x und y nicht berücksichtigt werden, da sie nur dazu dienen, die richtige Farbe zu ermitteln. Infolgedessen werden die AA-Zonen beider Eingänge über das gesamte Bild hinweg gemischt. Das resultierende AA-Kantenmuster stimmt nicht mit dem oben gerenderten Ergebnis überein. Außerdem ist die Diagonale, die im gerenderten Ergebnis sichtbar ist, in den AA-Zonen/AA-Kanten-Karten nicht sichtbar, was zu gezackten Kanten entlang dieser Linie führt:


Der Hauptpunkt dieser beiden Beispiele ist, dass der Ausführungspfad die Art und Weise beeinflusst, wie Filter Forge AA-Zonen aus Eingaben mit vom Skript erzeugten AA-Zonen kombiniert. Im ersten Beispiel führen unterschiedliche Ausführungspfade innerhalb der get_sample() -Funktion des Skripts dazu, dass unterschiedliche Eingaben gesampelt werden, was sich in den resultierenden AA-Zonen widerspiegelt. Im zweiten Beispiel führen alle Ausführungspfade dazu, dass beide Eingaben gesampelt werden, so dass ihre AA-Zonen immer zusammengemischt werden.
Außerdem ist das erste Skript wesentlich schneller als das zweite, weil es die Eingaben nur dann sampelt, wenn die zurückgegebene Farbe tatsächlich zur Berechnung der endgültigen Farbe verwendet wird, während das zweite Skript die Ergebnisse der Eingabe-Samples für 50% der gerenderten Pixel einfach verwirft.