WebGL - Translation: Moving Objects in 3D Space

Hallo, angehende WebGL-Entwickler! Heute machen wir uns auf eine aufregende Reise in die Welt der 3D-Grafik. Wir werden das Konzept der Translation in WebGL erkunden, was im Wesentlichen eine schicke Art ist, "Dinge herumzubewegen" zu sagen. Am Ende dieses Tutorials werdet ihr in der Lage sein, Objekte across euren Bildschirm tanzen zu lassen, wie in einem digitalen Ballett! Also, tauchen wir ein!

WebGL - Translation

Was ist Translation in WebGL?

Bevor wir anfangen, Dreiecke wie Schachfiguren hin und her zu bewegen, lassen wir uns zunächst klar machen, was Translation im Kontext der Computergrafik eigentlich bedeutet.

Die Grundlagen der Translation

Translation ist der Prozess des Verschiebens eines Objekts von einer Position zu einer anderen in einem 2D- oder 3D-Raum. Es ist so, als würde man eine Tasse von deinem Schreibtisch auf einen Regal stellen. Die Tasse (unser Objekt) hat von ihrer ursprünglichen Position zu einer neuen Position bewegt.

In WebGL verwenden wir Mathematik, um diese Bewegung zu erreichen. Keine Sorge, wenn du kein Mathe-Ass bist – WebGL erledigt die meiste schwere Arbeit für uns!

Warum ist Translation wichtig?

Stelle dir ein Videospiel vor, in dem die Charaktere nicht bewegen können, oder eine 3D-Modellierungssoftware, in der die Objekte feststecken. quite langweilig, oder? Translation ermöglicht es uns, dynamische, interaktive Grafiken zu erstellen, die auf Benutzerinput reagieren oder vorgegebene Animationen folgen.

Schritte zur Translation eines Dreiecks

Nun, da wir verstehen, was Translation ist, lassen uns den Prozess des Verschiebens eines einfachen Dreiecks in WebGL Schritt für Schritt durchgehen. Wir werden das in kleinen, leicht verständlichen Schritten machen.

Schritt 1: Definiere dein Dreieck

Zuerst müssen wir unser Dreieck erstellen. In WebGL definieren wir Formen mithilfe von Vertexen (Eckpunkten). Hier ist, wie wir ein einfaches Dreieck definieren könnten:

const vertices = [
0.0, 0.5,   // Oberer Vertex
-0.5, -0.5,  // Linker unterer Vertex
0.5, -0.5   // Rechter unterer Vertex
];

Dies erstellt ein Dreieck mit seiner oberen Spitze bei (0, 0.5) und seinen Basis-Ecken bei (-0.5, -0.5) und (0.5, -0.5).

Schritt 2: Erstelle eine Translation-Matrix

Um unser Dreieck zu bewegen, müssen wir eine Translation-Matrix erstellen. Diese Matrix tells WebGL, wie weit unser Objekt entlang jeder Achse (x, y und z) bewegt werden soll. Hier ist, wie wir eine Translation-Matrix erstellen:

const translationMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1
];

Wo tx und ty die Mengen sind, die wir entlang der x- und y-Achsen bewegen möchten.

Schritt 3: Wende die Translation im Vertex Shader an

Jetzt kommt der spannende Teil! Wir müssen unseren Vertex Shader so ändern, dass er die Translation anwendet. Hier ist ein einfacher Vertex Shader, der Translation enthält:

attribute vec2 a_position;
uniform mat4 u_translation;

void main() {
gl_Position = u_translation * vec4(a_position, 0, 1);
}

Dieser Shader nimmt jede Vertex-Position, konvertiert sie in einen 4D-Vektor (erforderlich für Matrizenmultiplikation) und multipliziert ihn dann mit unserer Translation-Matrix.

Schritt 4: Aktualisiere die Translation-Werte

Um unser Dreieck bewegen zu können, müssen wir die Translation-Werte im Laufe der Zeit aktualisieren. Wir können dies in unserem JavaScript-Code tun:

function updateAndDraw() {
tx += 0.01;  // Nach rechts bewegen
ty += 0.005; // Nach oben bewegen

// Aktualisiere die Translation-Matrix
gl.uniformMatrix4fv(translationLocation, false, translationMatrix);

// Zeichne das Dreieck
gl.drawArrays(gl.TRIANGLES, 0, 3);

requestAnimationFrame(updateAndDraw);
}

Diese Funktion aktualisiert unsere Translation-Werte, sendet die neue Matrix an die GPU und zeichnet dann unser Dreieck neu. Der Aufruf von requestAnimationFrame stellt sicher, dass dies flüssig, frame für frame, passiert.

Beispiel – Ein Dreieck translatieren

Lassen wir alles zusammenfließen mit einem vollständigen Beispiel. Dieses Code wird ein Dreieck erstellen, das diagonal across den Bildschirm bewegt:

// Vertex Shader
const vertexShaderSource = `
attribute vec2 a_position;
uniform mat4 u_translation;

void main() {
gl_Position = u_translation * vec4(a_position, 0, 1);
}
`;

// Fragment Shader
const fragmentShaderSource = `
precision mediump float;

void main() {
gl_FragColor = vec4(1, 0, 0, 1);  // Rote Farbe
}
`;

// Initialisiere WebGL
const canvas = document.getElementById('glcanvas');
const gl = canvas.getContext('webgl');

// Erstelle und komprimiere Shaders
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// Erstelle Programm
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// Erstelle Puffer und lade Vertex-Daten
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// Richte Attribut ein
const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// Richte Uniform ein
const translationLocation = gl.getUniformLocation(program, "u_translation");

// Translation-Variablen
let tx = 0;
let ty = 0;

function updateAndDraw() {
// Bereinige die Leinwand
gl.clear(gl.COLOR_BUFFER_BIT);

// Aktualisiere Translation
tx += 0.01;
ty += 0.005;

// Erstelle Translation-Matrix
const translationMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1
];

// Sende Matrix an Shader
gl.uniformMatrix4fv(translationLocation, false, translationMatrix);

// Zeichne
gl.drawArrays(gl.TRIANGLES, 0, 3);

// Fordere nächsten Frame an
requestAnimationFrame(updateAndDraw);
}

// Starte Animation
updateAndDraw();

Dieser Code erstellt ein rotes Dreieck, das diagonal across den Bildschirm bewegt. Lassen wir uns zusammenfassen, was passiert:

  1. Wir definieren unsere Shaders, die die Translation-Matrix enthalten.
  2. Wir richten WebGL ein, erstellen unser Programm und laden unsere Dreiecks-Vertices.
  3. Wir erstellen Variablen für unsere Translation (tx und ty).
  4. In unserer updateAndDraw-Funktion:
  • Bereinigen wir die Leinwand
  • Aktualisieren wir unsere Translation-Werte
  • Erstellen wir eine neue Translation-Matrix
  • Senden wir diese Matrix an die GPU
  • Zeichnen wir unser Dreieck
  • Fordern wir den nächsten Animation Frame an

Und voilà! Ihr habt ein bewegtes Dreieck in WebGL erstellt. Gratulation!

Schlussfolgerung

Translation in WebGL mag am Anfang komplex erscheinen, aber es geht wirklich nur darum, Objekte auf eine clevere Weise zu bewegen. Wir haben hier die Grundlagen behandelt, aber es gibt so viel mehr, was ihr mit Translation machen könnt – kombiniert es mit Drehungen und Skalierungen, erstellt komplexe Animationen oder sogar interaktive 3D-Umgebungen.

Denkt daran, jede Reise beginnt mit einem Schritt – oder in unserem Fall, einer Bewegung eines Dreiecks. Bleibt dran, experimentiert und bevor ihr es wisst, werdet ihr erstaunliche 3D-Grafiken erstellen, die sich bewegen und auf Weise interagieren, die ihr euch nie vorgestellt habt.

Frohes Coden und möge eure Dreiecke immer ihren Weg nach Hause finden!

Credits: Image by storyset