Filter Forge verwendet einen Sample-basierten Ansatz zur Bilderzeugung. Die Komponenten von Filter Forge erzeugen keine Bilder, indem sie ihre Pixel direkt malen. Stattdessen "fragt" Forge eine Komponente: "Welche Farbe hat dein Bild an den Koordinaten x und y?", und die Komponente "antwortet" mit vier RGBA-Werten. Mit anderen Worten: Das resultierende Bild wird implizit durch die Komponente definiert, anstatt explizit von ihr gemalt zu werden.
Um die Farbe an einem bestimmten Punkt des Bildes "abzufragen", ruft Filter Forge die Funktion get_sample() der Komponente mit den Koordinaten der Sample-Punkte als Argumente auf. Die Funktion berechnet dann die endgültige "Antwort" und gibt sie als vier RGBA-Werte zurück.
Während der Ausführung ihrer eigenen get_sample() -Funktion kann eine Komponente ihrerseits eine get_sample() -Funktion der Komponenten aufrufen, die mit ihren Eingängen verbunden sind, und die zurückgegebenen RGBA-Werte verwenden, um ihre eigene resultierende Farbe zu berechnen. Mit Ausnahme der Steuerkomponenten ist der Filterbaum, den du im Filter-Editor siehst, eine visuelle Darstellung des get_sample() -Aufrufgraphen.
Um einen Filter in eine Bitmap zu rendern, durchläuft der Renderer von Filter Forge alle Pixel und ruft die Funktion get_sample() der Wurzelkomponente des Filterbaums mindestens einmal pro Pixel auf (für kantengeglättete Pixel sind unter Umständen mehrere Aufrufe erforderlich, siehe unten.) Zum Beispiel würde die Erzeugung einer nicht-kantengeglätteten Bitmap mit den Abmessungen 30x30 Pixel 900 Aufrufe der Funktion get_sample() der Komponente erfordern.
Der Aufruf der Funktion get_sample() einer Komponente wird als Sampling bezeichnet, die Koordinaten des Punktes, dessen Farbe angefordert wird, als Sample-Koordinaten, und die zurückgegebene Farbe wird oft einfach als Sample bezeichnet.
Abbildungs-Komponenten (einschließlich Abbildungs-Skripte) verrichten ihre Arbeit, indem sie get_sample()-Funktionen von Komponenten aufrufen, die mit ihren Eingängen verbunden sind.
Eine Komponente, die einen get_sample() -Aufruf von einer "vorgelagerten" Komponente, mit der sie verbunden ist, oder direkt vom Filter Forge-Renderer erhalten hat, kann ihrerseits get_sample() von anderen Komponenten aufrufen, die mit ihren Eingängen verbunden sind. Auf diese Weise können Komponenten im Filterbaum Ergebnisse erhalten, die von ihren "nachgeschalteten" Komponenten erzeugt wurden, und diese zur Berechnung ihrer eigenen Ergebnisse verwenden.
Filter Forge-Komponenten können get_sample() ihrer Abbildungseingaben beliebig oft mit beliebigen Sample-Koordinaten aufrufen und die von diesen Aufrufen zurückgegebenen RGBA-Werte auf beliebige Weise kombinieren. Beispielsweise können Verzerrungskomponenten nachgelagerte Samples an anderen Koordinaten aufnehmen als in dem vorgelagerten Aufruf, den sie erhalten haben, angegeben. Ein weiteres Beispiel sind Anpassungskomponenten, die in der Regel nachgelagerte Samples an denselben Koordinaten aufnehmen, die in einem vorgelagerten Aufruf angegeben wurden – sie führen lediglich eine Art Farbkorrektur an der zurückgegebenen Sample-Farbe durch, die sie als Ergebnis zurückgeben.
Bitmap-basierte Komponenten wie Unschärfe, Scharfzeichnen oder Median, bilden eine Ausnahme vom Sample-basierten Ansatz. Ihre Algorithmen erfordern mehrere Lesevorgänge des Quellbildes, so dass es sinnvoll ist, es in einer Bitmap zwischenzuspeichern. All dies wird durch die übliche get_sample() -Funktion gekapselt, die in diesem Fall lediglich Pixel aus dem internen Bitmap-Cache holt und eine bikubische Filterung an ihnen vornimmt.
Kurven-Komponenten verwenden ebenfalls Sampling. Zusätzlich zu den Sample-Koordinaten enthalten die Argumente ihrer get_sample() -Funktion einen Parameter t, der das Argument ist, das an die durch die Kurve dargestellte Funktion übergeben wird (die Position auf der abscissa -Achse.)
Im Gegensatz zur Funktion get_sample() von Abbildungs-Komponenten, die RGBA-Werte zurückgibt, gibt die Funktion get_sample() on Kurven-Komponenten einen einzelnen numerischen Wert im Bereich von 0…1 zurück, der den Wert der Kurve am angegebenen Punkt (der Position auf der ordinate -Achse darstellt.)
Du frägst dich vielleicht, warum eine Kurven-Komponente die Koordinaten der Sample-Punkte benötigt. Das liegt daran, dass die Kurven-Komponenten von Filter Forge Abbildungs-Eingaben haben können und die von ihnen erzeugte Kurve daher an verschiedenen Sample-Punkten eine andere Form haben kann. Weitere Informationen darüber, wie die Parameterabbildung für Kurven funktioniert, findest du unter: Abbildungs-Eingaben.
Im Falle von Slave-Komponenten ist ein zusätzliches Argument der Funktion get_sample() in den Sampling-Vorgang einbezogen. Wenn eine Master-Komponente ihre Slave-Eingabe abtastet, fügt sie zusammen mit den Koordinaten des Sampling-Punkts ein zusätzliches Datenpaket hinzu. Wenn Slave-Komponenten, die zu dieser Master-Komponente gehören, bei der Ausführung ihrer get_sample() -Funktion auf das Datenpaket stoßen, ändern sie ihre Ausgabe entsprechend den von ihrem Master gesendeten Daten.
Technisch gesehen ist das von einem Master an seine Slaves gesendete Datenpaket ein zusätzliches Argument der Funktion get_sample(). Es enthält die ID der Master-Komponente, die es gesendet hat, und die Informationen für die Slave-Komponenten, auf deren Grundlage sie ihre Ausgabe ändern werden. Wenn Slave-Komponenten bei der Ausführung ihrer get_sample() -Funktion auf dieses Datenpaket stoßen, prüfen sie, ob die Master-Komponente, die es gesendet hat, ihr eigener Master ist, und wenn ja, ändern sie ihre Ausgabe entsprechend den im Paket enthaltenen Informationen. Normale Komponenten, die keine Slaves sind, reagieren nicht auf diese Datenpakete und übergeben sie einfach unverändert, wenn sie get_sample() für ihre eigenen Eingänge aufrufen.
Wenn beispielsweise eine Loop -Komponente ihren Akkumulator -Eingang sampelt, nimmt sie die Nummer der aktuellen Loop-Iteration in das Datenpaket auf. Dieses Paket wird zusammen mit den Punktkoordinaten als zusätzliches Argument beim Aufruf der Funktion get_sample() der mit Akkumulator verbundenen Komponente verwendet. Die an Akkumulator angeschlossene Komponente ist in der Regel eine normale (Nicht-Slave-) Komponente, so dass sie das Datenpaket nur an ihre eigenen Eingänge weitergibt, wenn sie diese abtastet. Wenn das Datenpaket schließlich eine Slave-Komponente diesen bestimmten Loop erreicht, z. B. den Iterations -Slave, liest die Slave-Komponente das Paket, ruft die Iterationsnummer ab, ändert sie gegebenenfalls und sendet sie an ihren Ausgang. Wenn das Datenpaket von einer Loop -Komponente kommt, die nicht der Master dieses bestimmten Slaves ist, oder von einer völlig anderen Master-Komponente (z.B. Bomber Plus), ändert der Slave seine Ausgabe nicht auf der Grundlage des Datenpakets
Wenn eine Slave-Komponente einen get_sample() -Aufruf ohne ein an sie "adressiertes" Datenpaket ausführt (sprich ein Datenpaket von einem anderen Master oder von einer Master-Komponente anderer Art), verwendet sie die Daten aus dem Paket nicht, um ihre eigene Ausgabe zu bilden. Stattdessen verwendet es seine Vorschaueinstellungen, um die Ausgabe zu erzeugen.
In jedem Fall leiten die Slaves bei der Ausführung ihrer get_sample() alle Datenpakete an ihre Eingänge weiter, unabhängig davon, ob sie auf das Datenpaket reagieren oder nicht. Das bedeutet, dass du Slaves mit den Eingängen anderer Slaves verbinden kannst und diese korrekt funktionieren.
Bitmap-basierte Komponenten (wie z.B. Unschärfe oder Bewegungsunschärfe) können die oben genannten Datenpakete nicht in ihren Eingabe- oder Ausgabe-Bitmap-Caches speichern. Das macht sie inkompatibel mit Slave-zu-Master-Verbindungen (mit Ausnahme der Komponente Ergebnis: siehe den Abschnitt "Slave-Komponenten verwenden" im Hilfeartikel für die Komponente Ergebnis.)
Ein Sampling-Punkt mit den Koordinaten 0, 0 entspricht der linken oberen Ecke des Bildes, und ein Punkt mit den Koordinaten 1, 1 entspricht der rechten unteren Ecke des Quadrats Größe x Größe Pixel Breite, wobei Größe der aktuelle Wert des globalen Schiebereglers Größe ist. Wenn Größe auf seinen Maximalwert eingestellt ist (der als Minimum zwischen Breite und Höhe des Quellbildes bestimmt wird) und das Bild quadratisch ist, entspricht der Punkt 1, 1 der rechten unteren Ecke des Bildes.
Die Abhängigkeit der Sample-Koordinaten vom Wert des Schiebereglers Größe mag kontraintuitiv und kompliziert erscheinen, aber tatsächlich befreit sie Skriptautoren davon, sich manuell mit Größe, Bildabmessungen und Seitenverhältnissen auseinandersetzen zu müssen. Sofern du kein fortgeschrittenes Skript schreibst, das unabhängig von der Größe sein muss, musst du dich nicht um die Größe oder die Bildabmessungen kümmern – du kannst einfach die wichtigen Elemente des Skript-Ausgabebilds im Bereich zwischen 0, 0 und 1, 1 halten.
Beide Sample-Koordinaten können sich über den Bereich 0…1 hinaus erstrecken, sowohl in positiver als auch in negativer Richtung. Im Wesentlichen implementiert eine Sample-basierte Komponente eine unendliche texturierte Ebene, so dass sie in der Lage sein muss, Sample-Anforderungen an beliebigen Koordinaten korrekt zu verarbeiten.
Die Komponenten dürfen nicht davon ausgehen, dass die Sample-Aufrufe, die sie erhalten, einer bestimmten Reihenfolge oder einem bestimmten Muster entsprechen. Eine Komponente muss in der Lage sein, ihre Farbe für jede Sample-Stelle zu jeder Zeit zu melden.
Das Sampling-Muster und die Reihenfolge können sich ändern, wenn eine Komponente von einer vorgeschalteten Verzerrungs- oder Transformationskomponente gesampelt wird, oder wenn Filter Forge intelligente Kantenglättung anwendet, bei dem einige Pixel mehr Samples erhalten als andere (insbesondere, wenn Sample-Jittering aktiviert ist), oder sogar aufgrund eines GUI-Szenarios, bei dem der Renderer den Renderblöcken, die derzeit im Vorschaubereich sichtbar sind, höhere Priorität einräumt.