Der Strich

Bis hierher ist ein Gesicht eine Liste von Punktzügen. Was daraus eine Zeichnung macht, sind drei Entscheidungen im Stift – und alle drei hängen daran, dass jedes Bild neu gezeichnet wird.

macheStift bekommt eine Zeichenfläche, einen Seed, eine Tintenfarbe, einen Maßstabsfaktor und einen Takt. Zurück kommen drei Werkzeuge: zug, flaeche, punkt. Mehr braucht der ganze Stil nicht. Alle Maße sind Einheitsmaße – der Aufrufer hat die Fläche längst auf Kopfgröße skaliert, eine Breite von 0.024 sind also gut zwei Prozent der Kopfhöhe.

Jeder Strich ist eine Fläche

Kein ctx.stroke(). Ein Zug ist ein Band: die Mittellinie plus die halbe Breite nach beiden Seiten, als ein einziges gefülltes Polygon. Der Grund ist die Breite selbst – sie soll sich innerhalb eines Zuges ändern: dünn beim Ansetzen, voll in der Mitte, dünn beim Abheben.

Eine Linie in Canvas hat eine Breite, und zwar überall dieselbe. Wer die Verjüngung trotzdem will, braucht einen stroke() je Teilstück. Bei neun Köpfen mal vierzig Zügen mal sechzig Bildern in der Sekunde ist das der Unterschied zwischen flüssig und zäh.

Die Druckkurve ist spitz: 0 heißt stumpfe Enden, 1 heißt spitz auslaufend, voreingestellt sind 0.75. Der Sinus-Anteil ist bewusst flach gehalten – eine Linie, die in der Mitte doppelt so dick ist wie an den Enden, sieht nach Pinsel aus, nicht nach Stift.

Das Band ist auch der Grund, warum es flaeche() als eigenes Werkzeug gibt und nicht nur einen geschlossenen Zug: eine Fläche hat keine Breite, sie hat einen Rand. Was mit ihr im Druck passiert, steht im Kapitel Der Druck.

Der Verzug hat einen Namen

Ein handgezeichneter Strich trifft seine Sollkurve nicht. Die naheliegende Umsetzung: ein Zufallsstrom, aus dem jeder Zug seine Abweichung zieht. Sie ist falsch, und zwar nicht ein bisschen.

Das flimmernde Gesicht

Symptom: Beim Blinzeln ändert nicht das Auge seine Form, sondern das halbe Gesicht – Nase, Mund und Wangen springen für drei Bilder auf eine andere Zeichnung um.

Ursache: Der Verzug hing an der Aufrufreihenfolge. Ein geschlossenes Lid ist ein Zug statt vier; alles, was danach gezeichnet wird, zieht seine Zufallszahlen um vier Stellen versetzt und ist deshalb ein anderer Strich.

Lösung: Der Verzug hängt an einer SPUR – einem Namen: "kontur", "auge-l". Gleicher Name plus gleicher Seed ergibt in jedem Bild dasselbe Zittern, egal was vorher oder gar nicht gezeichnet wurde.

Aus dem Namen wird über einen FNV-Hash ein Startwert, aus dem Startwert ein Feld von 52 Stützwerten. Es liegt in einer Map am Stift: dieselbe Spur wird je Bild mehrfach gebraucht, und ein Kopf hat keine hundert davon.

Die Linie kocht

Eine Handzeichnung, die sich bewegt, ist ein Trickfilm: jedes Bild ist eine eigene Zeichnung, und keine trifft die vorige genau. Also bekommt jede Spur einen TAKT dazu – TAKT_JE_SEKUNDE = 8. Innerhalb eines Takts steht alles still, zwischen zwei Takten rutscht jede Linie ein wenig.

Der Takt kommt nicht aus dem Stift, sondern von oben – der Stil rechnet ihn beim Zeichnen jedes Kopfes aus: takt = Math.floor(zeit * TAKT_JE_SEKUNDE + d.taktVersatz).

Der taktVersatz ist je Kopf gewürfelt. Ohne ihn setzen neun Köpfe im selben Moment neu an, und ein Blatt, das im Gleichtakt zuckt, sieht aus wie ein Bildfehler.

Im Stift werden dafür zwei Ströme gemischt: einer hängt nur am Seed – die Hand –, einer auch am Takt – das Bild. Die Mischung ist 0.62 zu 0.5. Nur der Bild-Strom, und die Linie springt bei jedem Takt woandershin; nur die Hand, und sie steht.

Sechzigmal in der Sekunde neu gewürfelt wäre Rauschen, achtmal ist ein Stift. Der Regler zeigt beides.

koch hängt an der Länge

Nicht jeder Zug darf gleich stark kochen. Ein Mund, der achtmal in der Sekunde Länge und Bogen wechselt, ist kein Stift mehr, sondern Unruhe. Deshalb misst zug() zuerst die Länge der Bahn:

Längekochwer
unter 0.40 – nur die HandMund, Braue, Nase, Stachel
0.4 bis 1.2gemischtLidbögen, Ohren
ab 1.21 – voll am TaktKontur, Haarmasse

Dieselbe Länge steuert auch die Stärke des Verzugs (kurz, gedeckelt auf die halbe Amplitude): der Verzug ist ein Maß im Kopfraum, und derselbe Betrag ist auf einer langen Kontur ein Schlingern, auf einer kurzen Braue aber ein Sprung des ganzen Strichs.

Daneben gibt es ruhig als harten Schalter. Augenringe, Schraffuren, Stirnfalten sind blass und fein – ihr Kochen läse sich nicht als Zittern der Hand, sondern als Flackern des Bildes.

Die zweite Lage

Unter jedem Zug liegt derselbe Zug noch einmal: halb so breit, bei 32 % Deckung – und mit eigenem Verzug (Spur name~, Amplitude 1.7-fach plus 0.004). Genau darin liegt der Bleistift: die zweite Lage liegt nicht auf der ersten, sondern daneben.

einlagig: true schaltet sie ab. Das gilt für Ränder von Farbflächen und für Zierrat, wo die Doppelung nur Matsch wäre – die blasse Unterlippe im Grinsen etwa ist ein Haar breit, eine zweite Lage daneben macht daraus einen Fleck.

Vom Punktzug zur Bahn

Bevor überhaupt ein Band entsteht, wird der Punktzug zu einer gleichmäßig abgetasteten Bahn: entdoppeln, dann catmull, dann Abtasten nach Bogenlänge. Ein Mund aus drei Punkten muss ein Bogen werden, kein Knick.

Der Zug, der um einen Schritt zappelt

Symptom: Kurze Linien – Brauen, Mundwinkel – zittern an ihren Enden, obwohl der Verzug an einer festen Spur hängt und gar nicht kochen dürfte.

Ursache: Die Schrittsumme trifft den Endpunkt nur bis auf Rundung. Ob der letzte Schritt gerade noch passt oder gerade nicht mehr, kippt mit jeder winzigen Längenänderung – und der Zug ist von Bild zu Bild um bis zu einen Schritt länger oder kürzer.

Lösung: Der Endpunkt gehört immer dazu. Liegt der letzte gesetzte Punkt weiter als einen halben Schritt entfernt, wird der Endpunkt angehängt; sonst ersetzt er ihn.

Geschlossene Züge laufen 3,5 % über den Anfang hinaus. Die Stelle, an der die Hand angesetzt hat, bleibt sichtbar – ein Kreis, der exakt in sich zurückläuft, ist eine Ellipse aus dem Zeichenprogramm.

Schlingern und Kratzen

Der Verzug selbst kommt aus zwei Wellen: einer groben mit 12 Stützwerten (das Schlingern) und einer feinen mit 40, mit 0.35 gewichtet (das Kratzen). Beide werden kubisch interpoliert.

Nur das Schlingern sähe aus wie ein Gummischlauch, nur das Kratzen wie ein Kurzschluss.

Ein Punkt ist kein Kreis

Ein gefüllter Kreis ist die Stelle, an der eine Zeichnung am schnellsten nach Vektorgrafik aussieht: ctx.arc trifft die Rundung exakt, und genau das erkennt das Auge – bei einer Pupille, einer Sommersprosse und einem Stoppelpunkt gleichermaßen.

Also geht punkt() denselben Weg wie jeder andere Zug: ein leicht ovaler, gekippter Ring, mit dem Rauschen dieses Stifts verzogen, darunter ein blasser Saum vom Ausbluten. Vier Details entscheiden:

Detailohne
eigene spur je Punkt zwei Pupillen mit derselben Beule an derselben Stelle – Zwillinge
Rand nicht geschlossen gerechnet das Rauschen läuft von 0 bis 1 und trifft am Ende nicht den Anfang; dort sitzt die Ansatzstelle
Verzug gedeckelt am Radius (0.15 r, höchstens 0.007) aus der Sommersprosse wird eine Amöbe
ohneSaum für Punkte, die AUF etwas liegen der Glanzpunkt im Auge bekommt einen blassen Rand und sieht aus wie ein Fleck

Ein Punkt kocht nicht. Er zieht seine Spur immer ruhig, ohne Takt. Eine Pupille, die je Takt woanders sitzt, ist ein Zittern, kein Strich.

Das feld ist die letzte Zutat: die vier Werte, die ein Feld ohnehin führt (ex, ey, fx, fy, siehe Raum). Ohne sie zeichnet der Punkt im Bildschirmraum – die Lidbögen eines gedrehten Kopfes stauchen sich, die Pupille darin bleibt ein voller Kreis und steht seitlich über die Kontur hinaus. Weggelassen wird das Feld für alles, was nicht auf dem Kopf liegt: eine Antennenkugel steht im Raum, keine Wange trägt sie.

Eine Hand zeichnet groß mit demselben Stift

Ein Kopf in der Großansicht ist dreimal so groß wie im Raster. Wüchse der Strich einfach mit, wäre er dort dreimal so dick – ein Filzstift. Ganz gleich bleiben darf er aber auch nicht: derselbe Pixelstrich, der groß richtig ist, ist im Raster ein Haar. Der Kommentar unten sagt, wie der Faktor zwischen beidem vermittelt.

Exponent 0.4, geklemmt auf 0.62 bis 1.3, Bezugsgröße 95 – die Größe, in der ein Kopf im Raster steht. Im Raster ist der Faktor also 1, in der Großansicht sinkt er gegen die Klemme.

Der Faktor wird einmal beim Anlegen des Stifts gesetzt (strichFaktor(at.mass)) und multipliziert danach jede Breite. Kein Zeichenschritt muss davon wissen.