Wie funktioniert dieser kleine fraktale Shader?

7

Ich würde gerne die Magie hinter diesem winzigen fraktalen Shader kennenlernen. Ich habe den Code und den erwähnten Thread nicht wirklich verstanden ...

Gibt es eine leicht zugängliche Erklärung?

https://www.shadertoy.com/view/4ttBWM

arthur.sw
quelle

Antworten:

10

Hier ist eine zeilenweise Aufschlüsselung meines Shaders:

#define mainImage(o,p)\
    for( vec2 r = iResolution.xy, q = 2.*(p+p-r)/r.y; o.a++ < 30.; )\
        o += length( q = abs(q)/dot(q,q) - iMouse.xy/r) / 2e2

Zunächst ist es wichtig zu wissen, dass das „\“ am Ende der ersten beiden Zeilen nicht zur Zeichenanzahl zählt und lediglich dazu dient, den Code besser lesbar zu machen, indem er in mehrere Zeilen aufgeteilt wird.

#define mainImage(o,p)

Beginnt mit der Definition der Funktion, die normalerweise als void mainImage (out fragColor, in fragCoord) geschrieben wird. {...} Dies spart einige Zeichen.

Der erste Teil der Schleife:

vec2 r = iResolution.xy, q = 2.*(p+p-r)/r.y;

Erstellt zwei Variablen vom Typ Vector2:

r ist die Auflösung, mit der ich mehrmals später in weniger Zeichen auf iResolution verweisen kann.

q ist die Koordinate im Fraktal, die aus dem fragCoord p berechnet und dann in jeder Schleife iteriert wird.

Anstelle von fragCoord, das bei (0,0) in der unteren linken Ecke beginnt und sich bis (rx, ry) in der oberen rechten Ecke erstreckt, transformiert (p + pr) jedes fragCoord so, dass die Mitte des Bildschirms (0,0) ist. . Dies verdoppelt den fragCoord-Wert und subtrahiert dann die Auflösung des Fensters. Die Division durch ry passt die Koordinaten so an, dass die Oberseite einen Wert von 1 und die Unterseite einen Wert von -1 hat. Damit wird das x entsprechend skaliert, ohne sich zu dehnen. Schließlich wird die Multiplikation mit 2 nur um den Faktor 2 verkleinert.

Dann benutze ich für den Iterator oa (den Alpha-Kanal von o). o ist die Ausgabefarbe, die ein vec4 ist. Wie von Shadertoy definiert, beginnt o mit dem Wert vec4 (0,0,0,1). Ich benutze dies, damit ich keine Zeichen verwenden muss, die einen neuen Float als Iterator deklarieren. o.a ++ <30 kombiniert den Testausdruck und den Iterator in der for-Schleife.

Der Inhalt der Schleife besteht aus einer Zeile, in der jedem Kanal der Ausgabefarbe eine Nummer hinzugefügt wird. Diese Linie:

o += length( q = abs(q)/dot(q,q) - iMouse.xy/r) / 2e2

Kann in einige Teile zerlegt werden. Jede Iteration der Koordinaten im Fraktal erfolgt hier:

q = abs(q)/dot(q,q) - iMouse.xy/r

Wobei iMouse.xy / r eine Möglichkeit ist, Mauskoordinaten von Pixel in den Bereich (0,0) bis (1,1) zu transformieren.

Jede Iteration dieser Funktion ändert den Wert von q, der verwendet werden soll.

Was dieses Fraktal erzeugt, ist die Idee, dass einige Anfangswerte für q ins Unendliche entkommen und andere konvergieren oder um einige kleine Werte herumlaufen. Mit jeder Iteration erhöhe ich die Helligkeit des Pixels basierend darauf, wie weit q von (0,0) entfernt ist. Diese Länge von q wird dann durch die Konstante 2e2 (200) geteilt, um zu verhindern, dass o.rgb zu schnell ansteigt.

Der Inhalt der Schleife kann in zwei Schritten verstanden werden:

q = abs(q)/dot(q,q) - iMouse.xy/r;
o += length(q) / 2e2;

Selbst wenn o in einem seiner Kanäle einen Wert enthält, der größer als 1 ist, wird es von Shadertoy automatisch geklemmt, und in der letzten Zeile wird kein nachfolgendes Semikolon benötigt.

mathmasterzach
quelle
Großartig! Wie haben Sie diese Formel gefunden abs(q)/dot(q,q) - iMouse.xy/r? Ist es empirische Forschung oder haben Sie eine Methode, um Formeln zu finden, die gute Eigenschaften haben?
arthur.sw
1
@ arthur.sw Ich habe diese Formel hier gefunden: link und sie dann an meinen Shader angepasst.
Mathmasterzach
1
Wenn Sie sich für Code-Golftechniken interessieren, haben wir auch eine Website dafür ... Sie stellen Herausforderungen für den Wettbewerb, akzeptieren aber auch Fragen mit dem Tag "Tipps", um Ratschläge zum Golfen im Allgemeinen oder zum Reduzieren eines bestimmten Codes zu erhalten.
Trichoplax