Essentielle Einfachheit

Ich möchte hier ein paar Funktionen darstellen, die sich bei meinem Start in die Welt der generativen Grafik und Animation schon fast wie von selbst in meinen Baukasten geschlichen haben. So ist es dann auch kein Zufall, dass sich diese in so ziemlich jeder Bibliothek zum Thema wiederfinden – mal unter anderen Namen, mal mit leichten Variationen. Das wirklich Schöne an Ihnen ist ihre Einfachheit und vermutlich daher rührend ihre unfassbar vielseitigen Anwendungsmöglichkeiten.

Es geht hier um mehr als um Helfer für einen simplen Dreisatz, denn ein besonders interessanter Aspekt ist die Verkettungsmöglichkeit dieser Funktionen: Durch Normalisierung auf den Raum zwischen 0 und 1 lassen sich Werte aus völlig unterschiedlichen Kontexten – sei es Scrollposition, Mausbewegung oder Zeit – einheitlich verarbeiten und dann wieder in den gewünschten Zielbereich transformieren. So entstehen komplexe Animationen oft aus der Kombination einfacher mathematischer Transformationen.

Normalize

const normalize = (min: number, max: number, value: number) => {
if (max - min === 0) {
throw new RangeError(
`Must be a range greater than 0. Given was a range with max: ${max} and min: ${min}`
);
}
return (value - min) / (max - min);
};

Die normalize-Funktion ist der erste Teil eines mächtigen Duos in der Wertetransformation. Sie wandelt einen Wert aus einem beliebigen Bereich in einen Wert zwischen 0 und 1 um – quasi eine Übersetzung in eine Universalsprache. Sie ist das exakte Gegenstück zu der im Folgenden beschriebenen Funktion lerp: Während normalize «nach innen» auf [0,1] abbildet, geht lerp «nach außen» in einen Zielbereich.

Diese Normalisierung berechnet die relative Position eines Wertes in seinem Bereich. Ein Wert genau in der Mitte ergibt 0.5, am unteren Ende 0, am oberen Ende 1. Zusammen mit lerp bildet sie das Fundament der remap-Funktion und ist essentiell für die Verarbeitung von Eingabewerten aller Art.

0.00
10.00

Lerp (Linear Interpolation)

const lerp = (a: number, b: number, t: number) => {
return a + t * (b - a);
};

Die lerp-Funktion (Linear Interpolation) ist der zweite Teil unseres Transformations-Duos. Als Gegenstück zu normalize nimmt sie einen normalisierten Wert zwischen 0 und 1 und überführt ihn in einen gewünschten Zielbereich. Wo normalize nach «innen» auf [0,1] abbildet, geht lerp «nach außen» in einen beliebigen Bereich.

Der Parameter t bestimmt dabei die relative Position im Zielbereich: Bei t=0 erhält man den Startwert, bei t=1 den Endwert, bei t=0.5 genau die Mitte. Gemeinsam mit normalize bildet lerp das mathematische Fundament für die remap-Funktion und ist unerlässlich für Animationen und Übergänge aller Art.

0.00
10.00

Clamp

export const clamp = (rangeStart: number, rangeEnd: number, value: number) => {
const _min = rangeStart < rangeEnd ? rangeStart : rangeEnd;
const _max = rangeStart < rangeEnd ? rangeEnd : rangeStart;
return Math.min(Math.max(_min, value), _max);
};

Die clamp-Funktion gehört zu den grundlegenden Werkzeugen in der Grafikprogrammierung. Sie begrenzt einen Wert auf ein definiertes Intervall und verhindert damit das Über- oder Unterschreiten festgelegter Grenzen – eine Aufgabe, die bei der Arbeit mit Koordinaten, Farben oder Animationsparametern ständig auftritt.

Statt verschachtelter Bedingungen erledigt ein einfacher clamp-Aufruf die Überprüfung: Unterschreitet der Eingabewert die untere Grenze, wird der Minimalwert zurückgegeben, überschreitet er die obere Grenze, der Maximalwert. Liegt der Wert innerhalb des definierten Bereichs, bleibt er unverändert.

Für den flexiblen Einsatz ist es wichtig, dass es egal ist, ob nun zuerst das Minimum oder das Maximum eingegeben wird.

0.30
0.70

Remap

const reMap = (
origMin: number,
origMax: number,
targetMin: number,
targetMax: number,
value: number
) => {
// Clamp input to original range
const numClamped = clamp(origMin, origMax, value);
// Normalize to 0-1
const normalizedValue = (numClamped - origMin) / (origMax - origMin);
// Scale to target range
return targetMin + normalizedValue * (targetMax - targetMin);
};

Die remap-Funktion ist ein mächtiges Werkzeug zur Transformation von Wertebereichen. Sie übersetzt einen Wert aus einem Ursprungsbereich proportional in einen Zielbereich. Dies ist besonders nützlich, wenn Daten aus verschiedenen Quellen harmonisiert oder ineinander übersetzt werden müssen.

Ob Sensordaten in Bildschirmkoordinaten, Mausbewegungen in Animationsfortschritt oder Dezibel in Prozentwerte – remap macht die Umrechnung elegant und nachvollziehbar. Intern nutzt die Funktion eine Kombination aus Normalisierung und linearer Interpolation.

Ursprungsbereich
0.00
10.00
Zielbereich
5.00
8.00

Smoothstep

const smoothStep = (x: number): number => {
if (x < 0 || x > 1) {
throw new Error("Input x must be between 0 and 1.");
}
return x * x * (3 - 2 * x);
};

Die smoothstep-Funktion ist der Meister der weichen Übergänge. Sie erzeugt eine S-förmige Kurve, die sanft beginnt, in der Mitte gleichmäßig ansteigt und zum Ende hin wieder weich ausläuft. Es handelt sich um eine einfache Variante einer Sigmoidfunktion, und findet Verwendung in vielen Grafikanwendungen (u.a. GLSL).

Mathematisch handelt es sich um ein Hermite-Polynom dritten Grades, das stetig und zweimal differenzierbar ist. In der Praxis bedeutet das: Perfekt geglättete Übergänge ohne ruckartigen Start oder abruptes Ende. Die Funktion erwartet einen Eingabewert zwischen 0 und 1 und ist besonders nützlich für Fade-Effekte, Kamera-Bewegungen oder das Überblenden zwischen Zuständen.