WebGL - Zeichnen eines Dreiecks

Hallo da draußen, zukünftige WebGL-Zauberer! Heute machen wir uns auf eine aufregende Reise in die Welt der Computergrafik. Wir werden lernen, wie man ein Dreieck mit WebGL zeichnet, was vielleicht einfach klingt, aber glaubt mir, es ist die Grundlage für all die erstaunlichen 3D-Grafiken, die ihr in Spielen und Filmen seht. Also, sichern und Tauchen wir ein!

WebGL - Drawing a Triangle

Was ist WebGL?

Bevor wir mit dem Zeichnen von Dreiecken beginnen, lassen Sie uns einen Moment innehalten, um zu verstehen, was WebGL ist. WebGL (Web Graphics Library) ist eine JavaScript-API, die es uns ermöglicht, ohne Verwendung von Plugins 2D- und 3D-Grafiken in Webbrowsern zu rendern. Es ist wie ein Superkraft, die es euch ermöglicht, atemberaubende Visuals direkt in eurem Webbrowser zu erstellen!

Schritte zum Zeichnen eines Dreiecks

Das Zeichnen eines Dreiecks in WebGL mag initially eine überwältigende Aufgabe erscheinen, aber keine Sorge! Wir werden es in handhabbare Schritte aufteilen. Hier ist, was wir tun müssen:

  1. Das HTML-Canvas einrichten
  2. Den WebGL-Kontext erhalten
  3. Den Vertex-Shader erstellen und kompilieren
  4. Den Fragment-Shader erstellen und kompilieren
  5. Ein Shader-Programm erstellen
  6. Die Dreiecksvertexe definieren
  7. Ein Puffer erstellen und die Vertexdaten laden
  8. Die Vertexattribute verknüpfen
  9. Das Dreieck zeichnen

Nun gehen wir jeden Schritt im Detail durch.

1. Das HTML-Canvas einrichten

Zuerst müssen wir ein Canvas in unserer HTML-Datei erstellen, auf dem WebGL unser Dreieck rendern wird. So machen wir das:

<canvas id="glCanvas" width="640" height="480"></canvas>

Dies erstellt ein Canvas mit der ID "glCanvas" und den Abmessungen 640x480 Pixel. Ihr könnt diese Abmessungen nach Bedarf anpassen.

2. Den WebGL-Kontext erhalten

Nun wechseln wir zu JavaScript. Wir müssen den WebGL-Kontext von unserem Canvas erhalten:

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Unable to initialize WebGL. Your browser may not support it.');
return;
}

Dieser Code findet unser Canvas, fordert den WebGL-Kontext an und überprüft, ob WebGL im Browser unterstützt wird.

3. Den Vertex-Shader erstellen und kompilieren

Ein Vertex-Shader ist ein Programm, das Vertexdaten verarbeitet. So erstellen wir einen:

const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);

Dieser Code definiert unsere Vertex-Shader-Quelle und eine Funktion zum Erstellen und Kompilieren von Shadern.

4. Den Fragment-Shader erstellen und kompilieren

Ein Fragment-Shader bestimmt die Farbe jedes Pixels. So erstellen wir einen:

const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

Dieser Fragment-Shader wird unser Dreieck rot färben.

5. Ein Shader-Programm erstellen

Nun müssen wir unsere Shader in ein Programm verknüpfen:

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return;
}

6. Die Dreiecksvertexe definieren

Lassen wir uns die Vertexe unseres Dreiecks definieren:

const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

Diese Koordinaten definieren ein Dreieck im Clipraum, wobei jeder Koordinate der Wertebereich von -1 bis 1 zugeordnet ist.

7. Ein Puffer erstellen und die Vertexdaten laden

Nun müssen wir einen Puffer erstellen und unsere Vertexdaten in ihn laden:

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

8. Die Vertexattribute verknüpfen

Wir müssen WebGL mitteilen, wie es unsere Vertexdaten interpretieren soll:

const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

9. Das Dreieck zeichnen

Schließlich können wir unser Dreieck zeichnen:

gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Alles zusammengefasst

Hier ist unser vollständiger Code zum Zeichnen eines Dreiecks:

// Get WebGL context
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Unable to initialize WebGL. Your browser may not support it.');
return;
}

// Vertex shader source
const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

// Fragment shader source
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// Create shader function
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

// Create shaders
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

// Create shader program
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return;
}

// Define vertices
const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

// Create buffer and load vertex data
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Link vertex attributes
const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

// Draw the triangle
gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Und daar habt ihr es! Ihr habt gerade euer erstes Dreieck mit WebGL gezeichnet. Es mag wie viele Schritte für ein einfaches Dreieck erscheinen, aber denken Sie daran, das ist die Grundlage für die Erstellung komplexer 3D-Grafiken. Jeder Schritt, den wir durchgegangen sind, ist entscheidend für eine fortgeschrittene Darstellung.

Fazit

Glückwunsch zum Zeichnen eures ersten WebGL-Dreiecks! Ihr habt den ersten Schritt in die aufregende Welt der Computergrafikprogrammierungen gemacht. Denkt daran, jede Reise beginnt mit einem einzigen Schritt - oder in unserem Fall, einem einzigen Dreieck. Übt weiter, erkundet weiter, und bald werdet ihr erstaunliche 3D-Grafiken erstellen, die die Menschen begeistern werden!

Hier ist eine Tabelle, die die wichtigsten WebGL-Methoden zusammenfasst, die wir verwendet haben:

Methode Beschreibung
getContext('webgl') Holt den WebGL-Renderkontext
createShader() Erstellt ein Shader-Objekt
shaderSource() Setzt die Quellcode eines Shaders
compileShader() Kompiliert einen Shader
createProgram() Erstellt ein Programm-Objekt
attachShader() Hängt einen Shader an ein Programm
linkProgram() Verknüpft ein Programm-Objekt
createBuffer() Erstellt ein Puffer-Objekt
bindBuffer() Binde ein Puffer-Objekt an ein Ziel
bufferData() Erstellt und initialisiert einen Pufferdatenspeicher
getAttribLocation() Gibt die Lage einer Attributvariablen zurück
vertexAttribPointer() Definiert die Anordnung der Vertexattribute
enableVertexAttribArray() Aktiviert eine Vertexattributgruppe
useProgram() Setzt das angegebene Programm als Teil des aktuellen Renderstatus
drawArrays() Render Primitive aus Array-Daten

Behaltet diese Tabelle bereit, während ihr eure WebGL-Reise fortsetzt. Frohes Coden und möge eure Dreiecke stets perfekt gerendert sein!

Credits: Image by storyset