Vertex Shader
Betrachten wir nun den Vertex-Shader aus unserem vollständigen Beispiel mit der beleuchteten Kugel und dem prozeduralen Streifenmuster.
struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldNormal: vec3f, @location(1) worldPosition: vec3f,};
struct Uniforms { color: vec4f, lightDirection: vec4f, cameraPosition: vec4f,
ambientFactor: f32, diffuseStrength: f32, shininess: f32, padding: f32,
modelMatrix: mat4x4f, viewMatrix: mat4x4f, projectionMatrix: mat4x4f, normalMatrix: mat4x4f,};
@group(0) @binding(0)var<uniform> uniforms: Uniforms;
@vertexfn vertexMain( @location(0) position: vec3f, @location(1) normal: vec3f) -> VertexOutput { let worldPosition = uniforms.modelMatrix * vec4f(position, 1.0);
let viewPosition = uniforms.viewMatrix * worldPosition;
let clipPosition = uniforms.projectionMatrix * viewPosition;
let worldNormal = normalize( (uniforms.normalMatrix * vec4f(normal, 0.0)).xyz );
return VertexOutput( clipPosition, worldNormal, worldPosition.xyz );}Auf den ersten Blick enthält dieser Shader einige neue Berechnungen. Vieles sollten wir inzwischen aber bereits wiedererkennen.
Die Eingabeparameter position und normal sind Vertex-Attribute, die über @location(0) und @location(1) mit den Vertex-Buffern verbunden werden.
Mit @group(0) und @binding(0) greifen wir auf einen Uniform-Buffer zu. Die Struktur Uniforms enthält Werte, die unser JavaScript-Programm bereitstellt.
Auch die Struktur VertexOutput ist uns vertraut. Sie enthält die berechnete Vertex-Position sowie zwei Interstage-Variablen, die an den Fragment-Shader weitergegeben und dabei interpoliert werden.
Innerhalb der Funktion begegnen uns außerdem bekannte WGSL-Datentypen wie vec3f, vec4f und mat4x4f, die Funktion normalize() sowie der Zugriff auf Vektorkomponenten mit .xyz.
Was ist noch neu?
Abschnitt betitelt „Was ist noch neu?“Die vier Matrizen modelMatrix, viewMatrix, projectionMatrix und normalMatrix haben wir bisher noch nicht näher behandelt.
Sie werden verwendet, um die Positionen und Normalen der Kugel in unterschiedliche Koordinatensysteme zu transformieren. Die Berechnungen hängen mit der Positionierung von Objekten, der Kamera und der perspektivischen Darstellung zusammen.
Diese Themen behandeln wir später ausführlich im Kapitel über Kameras und Transformationen. Für den Moment genügt es zu wissen, dass der Vertex-Shader die Position jedes Vertex für die Darstellung vorbereitet und die benötigten Oberflächendaten an den Fragment-Shader weitergibt.