Zum Inhalt springen

Vektorkomponenten und Swizzling

Im vorherigen Kapitel haben wir gesehen, wie wir mit Vektoren mehrere Zahlen zu einem Wert zusammenfassen können. Ein vec3f enthält beispielsweise drei Komponenten, ein vec4f vier.

Häufig benötigen wir aber nicht den gesamten Vektor, sondern nur einzelne Komponenten. WGSL bietet dafür eine einfache Schreibweise mit dem Punktoperator.

Betrachten wir einen Vektor mit vier Komponenten:

WGSL
let position = vec4f(2.0, 4.0, 6.0, 1.0);

Mit .x, .y, .z und .w können wir auf die einzelnen Werte zugreifen:

WGSL
let x = position.x; // 2.0
let y = position.y; // 4.0
let z = position.z; // 6.0
let w = position.w; // 1.0

Die Bezeichnungen orientieren sich an den Koordinaten eines Vektors. Für Farben bietet WGSL zusätzlich die Namen .r, .g, .b und .a.

Komponenten Typische Verwendung
x, y, z, w Positionen, Richtungen und Texturkoordinaten
r, g, b, a Farben: Rot, Grün, Blau und Alpha

Beide Schreibweisen greifen auf dieselben Komponenten zu. Der Unterschied liegt nur in ihrer Bedeutung für uns als Programmierer.

WGSL
let color = vec4f(0.8, 0.4, 0.2, 1.0);
let red = color.r; // 0.8
let alpha = color.a; // 1.0
let sameRed = color.x; // ebenfalls 0.8
let sameAlpha = color.w; // ebenfalls 1.0

Bei Farben sind rgba meist leichter zu verstehen, bei Positionen und Richtungen dagegen xyzw.

Welche Komponenten wir ansprechen können, hängt von der Größe des Vektors ab. Ein vec2f besitzt nur .x und .y beziehungsweise .r und .g. Der Zugriff auf .z wäre hier ungültig.

Wir können auch mehrere Komponenten eines Vektors gleichzeitig auswählen. Diese Schreibweise heißt Swizzling.

WGSL
let color = vec4f(0.8, 0.4, 0.2, 1.0);
let rgb = color.rgb;

color.rgb wählt die ersten drei Komponenten aus. Das Ergebnis ist ein vec3f mit den Werten 0.8, 0.4 und 0.2.

Diese Schreibweise haben wir bereits in unserem Phong-Shader verwendet:

WGSL
let color = uniforms.color.rgb;

Unsere Uniform-Farbe ist ein vec4f. Für die Beleuchtungsberechnung benötigen wir jedoch nur die drei Farbkomponenten Rot, Grün und Blau. Mit .rgb erhalten wir sie direkt als vec3f.

Auch bei Positionen können wir mehrere Komponenten auswählen:

WGSL
let position = vec3f(2.0, 4.0, 6.0);
let xy = position.xy; // vec2f(2.0, 4.0)
let xz = position.xz; // vec2f(2.0, 6.0)

Die Anzahl der ausgewählten Komponenten bestimmt den Typ des Ergebnisses:

Ausdruck Ergebnis Typ
position.x 2.0 f32
position.xy (2.0, 4.0) vec2f
position.xyz (2.0, 4.0, 6.0) vec3f

Beim Swizzling müssen wir die ursprüngliche Reihenfolge nicht beibehalten.

WGSL
let color = vec4f(0.8, 0.4, 0.2, 1.0);
let reversed = color.bgr;

reversed enthält vec3f(0.2, 0.4, 0.8). Die roten und blauen Farbkomponenten haben ihre Plätze getauscht.

Wir dürfen Komponenten auch mehrfach auswählen:

WGSL
let repeated = color.rrr;

Das Ergebnis ist vec3f(0.8, 0.8, 0.8).

Damit können wir beispielsweise aus einer einzelnen Farbkomponente einen Vektor mit drei gleichen Werten bilden.

Auch Kombinationen wie .xyx oder .wzyx sind möglich. Ein Swizzle darf eine bis vier Komponenten enthalten.

Bei der Schreibweise müssen wir zwei Regeln beachten.

1. Die ausgewählten Komponenten müssen vorhanden sein.

Ein vec2f enthält nur zwei Komponenten. Deshalb ist .xy gültig, .xyz dagegen nicht.

WGSL
let uv = vec2f(0.5, 0.25);
let swapped = uv.yx; // gültig
// let invalid = uv.xyz; // ungültig

2. Die Bezeichnungen dürfen innerhalb eines Swizzles nicht gemischt werden.

WGSL erlaubt die beiden Namensgruppen xyzw und rgba. Innerhalb eines Ausdrucks müssen wir aber bei einer Gruppe bleiben.

WGSL
let color = vec4f(0.8, 0.4, 0.2, 1.0);
let a = color.xyz; // gültig
let b = color.rgb; // gültig
// let c = color.xgb; // ungültig

Die Bezeichnungen s, t, p und q, die wir möglicherweise aus GLSL kennen, gehören nicht zu den WGSL-Komponentennamen.

Bisher haben wir Komponenten nur gelesen. Bei einer veränderbaren Variablen können wir ihnen auch neue Werte zuweisen.

WGSL
var color = vec4f(0.8, 0.4, 0.2, 1.0);
color.r = 1.0;
color.g = 0.5;

Danach enthält color die Werte vec4f(1.0, 0.5, 0.2, 1.0).

Auch mehrere Komponenten können wir gleichzeitig verändern:

WGSL
var position = vec3f(1.0, 2.0, 3.0);
position.xy = vec2f(5.0, 6.0);

Anschließend enthält position den Wert vec3f(5.0, 6.0, 3.0).

Bei einer Zuweisung dürfen die ausgewählten Komponenten nicht mehrfach vorkommen. Ein Ausdruck wie position.xx = vec2f(5.0, 6.0) wäre ungültig, weil wir dieselbe Komponente zweimal beschreiben würden.

Bei einer mit let deklarierten Variablen sind solche Änderungen ebenfalls nicht erlaubt, da ihr Wert nicht neu zugewiesen werden kann.

Mit dem Punktoperator können wir auf die Komponenten eines Vektors zugreifen:

  • .x, .y, .z, .w verwenden wir vor allem für Koordinaten und Richtungen.
  • .r, .g, .b, .a eignen sich für Farben.
  • Mit Swizzling wie .xy, .rgb oder .bgr wählen wir mehrere Komponenten aus und können sie neu anordnen.
  • Komponenten dürfen beim Lesen mehrfach vorkommen, bei einer Zuweisung jedoch nicht.

Swizzling macht WGSL-Code kompakter und lesbarer. Statt einen neuen Vektor aus einzelnen Komponenten zusammenzusetzen, können wir häufig direkt die benötigten Werte auswählen.