WebGL - Grafik-Pipeline

Hallo那里,有抱负的程序开发者们!今天,我们将踏上一段令人兴奋的旅程,探索 WebGL Grafik-Pipeline。如果你是编程新手,不用担心——我会成为你友好的向导,我们会一步一步地进行。在本教程结束时,你将有一个扎实的理解,了解 WebGL 如何将你的代码转换成屏幕上的惊人视觉效果。

WebGL - Graphics Pipeline

JavaScript: Der Ausgangspunkt

Bevor wir uns in die Tiefen von WebGL stürzen, beginnen wir mit etwas Vertrautem – JavaScript. WebGL wird über JavaScript angesprochen, was es zum perfekten Einstiegspunkt für unser Abenteuer macht.

Dein Erstes WebGL-Programm

Lassen wir mit einem einfachen Beispiel beginnen:

// Hole das Canvas-Element
const canvas = document.getElementById('myCanvas');

// Hole den WebGL-Kontext
const gl = canvas.getContext('webgl');

// Setze die Clear-Farbe (Hintergrundfarbe)
gl.clearColor(0.0, 0.0, 0.0, 1.0);

// Bereinige das Canvas
gl.clear(gl.COLOR_BUFFER_BIT);

In diesem Code-Snippet machen wir einige Dinge:

  1. Wir holen eine Referenz zu unserem HTML Canvas-Element.
  2. Wir erhalten den WebGL-Render-Kontext.
  3. Wir setzen die Clear-Farbe (in diesem Fall schwarz).
  4. Wir bereinigen das Canvas mit unserer angegebenen Farbe.

Das mag nicht viel erscheinen, aber Gratulation! Du hast dein erstes WebGL-Programm erstellt. Es ist, als ob du ein leeres Canvas für ein Meisterwerk vorbereitet hast.

Vertex Shader: Gestaltung Deiner Welt

Nun, da wir unser Canvas bereit haben, sprechen wir über Vertex-Shaders. Stell dir Vertex-Shaders als Bildhauer deiner 3D-Welt vor. Sie arbeiten mit den rohen Daten deiner Objekte – den Vertexen.

Ein Einfacher Vertex Shader

Hier ist ein Beispiel eines grundlegenden Vertex-Shaders:

attribute vec4 a_position;

void main() {
gl_Position = a_position;
}

Dieser Shader macht etwas Einfaches, aber Kritisches – er nimmt die Position jedes Vertex und weist sie gl_Position zu. Es ist, als würde man jedem Punkt deines 3D-Objekts sagen: "Du gehst hier hin!"

Primitive Assembly: Verbinde Die Punkte

Nachdem der Vertex Shader seine Arbeit erledigt hat, bewegt sich WebGL zur Primitive Assembly. Diese Stufe ist wie "Verbinde die Punkte" – sie nimmt die einzelnen Vertexen und.figureiert heraus, wie sie miteinander verbunden werden sollten, um Formen zu bilden.

Zum Beispiel, wenn du ein Dreieck zeichnest, würde die Primitive Assembly drei Vertexen nehmen und verstehen, dass sie ein einzelnes Dreieck bilden.

Rasterisierung: Pixel Überall

Nun kommt die Magie der Rasterisierung. Diese Stufe verwandelt unsere 3D-Formen in die 2D-Pixel, die du auf deinem Bildschirm siehst. Es ist, als ob man eine 3D-Skulptur nimmt und ein detailliertes Foto davon erstellt.

Fragment Shader: Male Deine Welt

Der Fragment Shader ist, wo die wahre Kunstfertigkeit stattfindet. Während der Vertex Shader sich um die Struktur deiner Objekte gekümmert hat, färbt der Fragment Shader sie ein.

Ein Einfacher Fragment Shader

Hier ist ein grundlegender Fragment Shader, der alles rot färbt:

precision mediump float;

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

Dieser Shader setzt gl_FragColor auf einen Vektor, der die Farbe Rot darstellt (volle Rot, keine Grün, keine Blau, volle Deckkraft). Es ist, als ob man seine ganze 3D-Welt in rote Farbe taucht!

Fragment Operationen: Die Letzten Touches

Nach dem Fragment Shader führt WebGL verschiedene Operationen auf den Fragmenten durch. Dies umfasst Tiefentests (bestimmt, welche Objekte vor anderen sind), Mischung (wie transparente Objekte interagieren) und mehr.

Frame Buffer: Das Gross Finale

Schliesslich erreichen wir den Frame Buffer. Dies ist, wo dein gerendertes Bild gespeichert wird, bevor es auf dem Bildschirm angezeigt wird. Es ist wie der Backstage-Bereich, wo die letzten Touches vor dem Vorhangaufgang angewendet werden.

Alles Zusammenfügen

Nun, da wir durch jede Stufe gegangen sind, sehen wir, wie sie alle in einem vollständigen WebGL-Programm zusammenarbeiten:

// Vertex Shader Quellcode
const vsSource = `
attribute vec4 aVertexPosition;

void main() {
gl_Position = aVertexPosition;
}
`;

// Fragment Shader Quellcode
const fsSource = `
precision mediump float;

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

// Initialisiere Shaders
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);

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

// Erstelle Shader-Programm
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

// Verwende das Programm
gl.useProgram(shaderProgram);

// Erstelle Buffer und übermittle Daten
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
1.0,  1.0,
-1.0,  1.0,
1.0, -1.0,
-1.0, -1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// Sage WebGL, wie er die Positionen aus dem Position Buffer in das VertexPosition Attribut zieht
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.vertexAttribPointer(
gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexPosition'));

// Zeichne die Szene
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

Dieses Programm erstellt ein einfaches rotes Quadrat auf einem schwarzen Hintergrund. Lassen Sie es aufschlüsseln:

  1. Wir definieren unsere Vertex- und Fragment-Shaders.
  2. Wir kompilieren diese Shaders und verknüpfen sie in ein Programm.
  3. Wir erstellen einen Buffer mit den Positionen der Vertexen unseres Quadrats.
  4. Wir sagen WebGL, wie er diese Buffer-Daten interpretieren soll.
  5. Schliesslich bereinigen wir den Bildschirm und zeichnen unser Quadrat.

Jeder Schritt entspricht einer Stufe in der Grafik-Pipeline, die wir besprochen haben. Es ist, als ob man einer Produktionslinie zuschaut, wo Rohstoffe (Vertex-Daten) in ein fertiges Produkt (Pixel auf deinem Bildschirm) verwandelt werden.

Methoden Tabelle

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

Methode Beschreibung
gl.createShader() Erstellt ein Shader-Objekt
gl.shaderSource() Setzt den Quellcode eines Shaders
gl.compileShader() Kompiliert einen Shader
gl.createProgram() Erstellt ein Programm-Objekt
gl.attachShader() Hängt einen Shader an ein Programm an
gl.linkProgram() Verknüpft ein Programm-Objekt
gl.useProgram() Setzt das angegebene Programm als Teil des aktuellen Render-Zustands
gl.createBuffer() Erstellt ein Buffer-Objekt
gl.bindBuffer() Bindet ein Buffer-Objekt an ein Ziel
gl.bufferData() Erstellt und initialisiert den Daten Speicher eines Buffer-Objekts
gl.vertexAttribPointer() Specifiziert die Anordnung der Vertex-Daten
gl.enableVertexAttribArray() Aktiviert eine Vertex-Attribut-Anzeige
gl.clearColor() Specifiziert die Farbe, die verwendet wird, um Farb-Buffer zu bereinigen
gl.clear() Bereinigt Buffer zu voreingestellten Werten
gl.drawArrays() Render_primitive aus Array-Daten

Und das ist es! Wir sind durch die WebGL Grafik-Pipeline gereist, von JavaScript bis zum finalen Frame Buffer. Denke daran, dass das Beherrschen von WebGL wie jede andere Fähigkeit Übung erfordert. Aber mit jeder Zeile Code, die du schreibst, kommst du näher, um erstaunliche 3D-Grafiken in deinem Web-Browser zu erstellen. Weiter experimentieren, weiter lernen und vor allem: Spass haben!

Credits: Image by storyset