Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Ihr erster 2D-Shader

Einführung

Shader sind spezielle Programme, die auf dem Grafikprozessor ausgeführt und zum Rendern von Grafiken verwendet werden. Das gesamte moderne Rendering wird mit Shadern durchgeführt. Eine genauere Beschreibung der Shader finden Sie unter Was sind Shader.

Dieses Tutorial konzentriert sich auf die praktischen Aspekte der Erstellung von Shader-Programmen, indem es Sie durch den Prozess der Erstellung eines Shaders mit Vertex- und Fragment-Funktionen führt. Dieses Tutorial richtet sich an absolute Anfänger im Bereich Shader.

Bemerkung

Wenn Sie Erfahrung mit dem Schreiben von Shadern haben und nur einen Überblick über die Funktionsweise von Shadern in Godot suchen, lesen Sie die Shading Reference.

Einrichtung

CanvasItem-Shader werden verwendet, um alle 2D-Objekte in Godot zu zeichnen, während Spatial-Shader verwendet werden, um alle 3D-Objekte zu zeichnen.

Um einen Shader zu verwenden, muss er innerhalb eines Materials angehängt sein, das wiederum an ein Objekt angehängt sein muss. Materialien sind ein Typ von Ressource. Um mehrere Objekte mit demselben Material zu zeichnen, muss das Material an jedes Objekt angehängt werden.

Alle Objekte, die von einem CanvasItem abgeleitet sind, haben eine Material-Property. Dazu gehören alle GUI-Elemente, Sprite2Ds, TileMaps, MeshInstance2Ds usw. Sie haben auch die Möglichkeit, das Material ihrer Eltern zu erben. Dies kann nützlich sein, wenn Sie eine große Anzahl von Nodes haben, die das gleiche Material verwenden sollen.

Zu Beginn erstellen Sie einen Sprite2D-Node. Sie können ein beliebiges CanvasItem verwenden, solange es auf den Canvas zeichnet. Für dieses Tutorial werden wir ein Sprite2D verwenden, da es das einfachste CanvasItem ist, um mit dem Zeichnen zu beginnen.

In the Inspector, click beside "Texture" where it says "[empty]" and select "Load", then select "icon.svg". For new projects, this is the Godot icon. You should now see the icon in the viewport.

Schauen Sie im Inspektor nach unten im Abschnitt CanvasItem, klicken Sie neben "Material" und wählen Sie "Neues ShaderMaterial". Dadurch wird eine neue Materialressource erstellt. Klicken Sie auf die erscheinende Kugel. Godot weiß derzeit nicht, ob Sie einen CanvasItem-Shader oder einen Spatial-Shader schreiben, und zeigt eine Vorschau der Ausgabe von Spatial-Shadern an. Was Sie also sehen, ist die Ausgabe des Default-Spatial-Shaders.

Klicken Sie neben "Shader" und wählen Sie "Neuer Shader". Klicken Sie schließlich auf den soeben erstellten Shader und der Shader-Editor wird geöffnet. Sie können nun mit dem Schreiben Ihres ersten Shaders beginnen.

Ein erster CanvasItem-Shader

In Godot beginnen alle Shader mit einer Zeile, die angibt, um welche Art von Shader es sich handelt. Dabei wird das folgende Format verwendet:

shader_type canvas_item;

Da wir einen CanvasItem-Shader schreiben, geben wir canvas_item in der ersten Zeile an. Unser gesamter Code wird unterhalb dieser Deklaration stehen.

Diese Zeile teilt der Engine mit, welche Buit-in-Variablen und -Funktionen Sie bereitstellen soll.

In Godot können Sie drei Funktionen überschreiben, um zu kontrollieren, wie der Shader arbeitet: Vertex, Fragment und Licht. Dieses Tutorial wird Sie durch das Schreiben eines Shaders mit Vertex- und Fragmentfunktionen führen. Lichtfunktionen sind wesentlich komplexer als Vertex- und Fragmentfunktionen und werden daher hier nicht behandelt.

Ihre erste Fragmentfunktion

Die Fragment-Funktion wird für jedes Pixel in einem Sprite2D ausgeführt und bestimmt, welche Farbe dieses Pixel haben soll.

Sie sind auf die vom Sprite2D abgedeckten Pixel beschränkt, d.h. man kann sie nicht verwenden, um z.B. einen Umriss um ein Sprite2D zu erstellen.

Die einfachste Fragmentfunktion tut nichts anderes, als jedem Pixel eine einzelne Farbe zuzuweisen.

Wir tun dies, indem wir einen vec4 in die Built-in-Variable COLOR schreiben. vec4 ist eine Abkürzung für das Konstruieren eines Vektors mit 4 Zahlen. Für weitere Informationen über Vektoren siehe das Vector math tutorial. COLOR ist sowohl eine Eingabevariable für die Fragmentfunktion als auch die endgültige Ausgabe der Funktion.

void fragment(){
  COLOR = vec4(0.4, 0.6, 0.9, 1.0);
}
../../../_images/blue-box.png

Herzlichen Glückwunsch! Sie sind fertig. Sie haben erfolgreich Ihren ersten Shader in Godot geschrieben.

Lassen Sie uns die Dinge jetzt komplexer machen.

Es gibt viele Eingaben für die Fragment-Funktion, die Sie für die Berechnung von COLOR verwenden können. UV ist einer davon. UV-Koordinaten werden in Ihrem Sprite2D angegeben (ohne dass Sie es wissen!) und sie sagen dem Shader, wo er die Texturen für jeden Teil des Meshes auslesen soll.

In der Fragmentfunktion können Sie nur von UV lesen, aber Sie können es in anderen Funktionen verwenden oder COLOR direkt Werte zuweisen.

UV variiert zwischen 0-1 von links nach rechts und von oben nach unten.

../../../_images/iconuv.png
void fragment() {
  COLOR = vec4(UV, 0.5, 1.0);
}
../../../_images/UV.png

Verwenden des TEXTURE-Built-ins

The default fragment function reads from the set Sprite2D texture and displays it.

When you want to adjust a color in a Sprite2D you can adjust the color from the texture manually like in the code below.

void fragment(){
  // This shader will result in a blue-tinted icon
  COLOR.b = 1.0;
}

Certain nodes, like Sprite2Ds, have a dedicated texture variable that can be accessed in the shader using TEXTURE. If you want to use the Sprite2D texture to combine with other colors, you can use the UV with the texture function to access this variable. Use them to redraw the Sprite2D with the texture.

void fragment(){
  COLOR = texture(TEXTURE, UV); // Read from texture again.
  COLOR.b = 1.0; //set blue channel to 1.0
}
../../../_images/blue-tex.png

Uniform-Eingabe

Uniform-Eingabe wird verwendet, um Daten in einen Shader zu übertragen, die im gesamten Shader gleich sind.

Sie können Uniforms verwenden, indem Sie sie oben im Shader wie folgt definieren:

uniform float size;

Weitere Informationen über Godots Shader-Sprache gibt es im eigenen Artikel: Shading-Sprach-Dokumentation.

Fügen Sie ein Uniform hinzu, um die Menge an Blau in unserem Sprite2D zu ändern.

uniform float blue = 1.0; // you can assign a default value to uniforms

void fragment(){
  COLOR = texture(TEXTURE, UV); // Read from texture
  COLOR.b = blue;
}

Jetzt können Sie den Blauanteil im Sprite2D über den Editor ändern. Schauen Sie im Inspektor unter der Stelle nach, an der Sie Ihren Shader erstellt haben. Sie sollten einen Abschnitt namens "Shader Param" sehen. Klappen Sie diesen Abschnitt auf und Sie werden das Uniform sehen, das Sie gerade deklariert haben. Wenn Sie den Wert im Editor ändern, wird der Defaultwert, den Sie im Shader angegeben haben, überschrieben.

Interaktion mit Shadern aus Code

Sie können Uniforms vom Code aus ändern, indem Sie die Funktion set_shader_parameter() verwenden, die auf der Materialressource des Nodes aufgerufen wird. Bei einem Sprite2D-Node kann der folgende Code verwendet werden, um das blaue Uniform zu setzen.

var blue_value = 1.0
material.set_shader_parameter("blue", blue_value)

Beachten Sie, dass der Name des Uniforms ein String ist. Der String muss genau mit der Schreibweise im Shader übereinstimmen, einschließlich Rechtschreibung und Groß-/Kleinschreibung.

Ihre erste Vertex Funktion

Da wir nun eine Fragment-Funktion haben, schreiben wir eine Vertex-Funktion.

Verwenden Sie die Vertex-Funktion zur Berechnung, wo auf dem Bildschirm jeder Vertex landen soll.

Die wichtigste Variable in der Vertex-Funktion ist VERTEX. Anfänglich gibt sie die Koordinaten der Vertices in Ihrem Modell an, aber Sie schreiben auch in sie, um zu bestimmen, wo diese Vertices tatsächlich gezeichnet werden sollen. VERTEX ist eine vec2, die anfänglich im lokalen Raum dargestellt wird (d.h. nicht relativ zur Kamera, dem Viewport oder den übergeordneten Nodes).

Sie können die Vertices mit einem Offset verschieben, indem Werte zu VERTEX addieren.

void vertex() {
  VERTEX += vec2(10.0, 0.0);
}

In Kombination mit der Built-in-Variable TIME kann diese für einfache Animationen verwendet werden.

void vertex() {
  // Animate Sprite2D moving in big circle around its location
  VERTEX += vec2(cos(TIME)*100.0, sin(TIME)*100.0);
}

Fazit

Im Kern tun Shader das, was Sie bisher gesehen haben: Sie berechnen VERTEX und COLOR. Es liegt an Ihnen, sich komplexere mathematische Strategien für die Zuweisung von Werten zu diesen Variablen auszudenken.

Um sich zu inspirieren, schauen Sie sich einige der fortgeschritteneren Shader-Tutorials an, und schauen Sie sich andere Seiten wie Shadertoy und The Book of Shaders an.