Fragment Shader ist eine programmierbare Stufe der Grafikpipeline, die die endgültige Farbe jedes Fragments (Pixels) eines Bildes bestimmt. Laut Khronos Group, 2025 empfängt der Fragment-Shader interpolierte Daten vom Vertex Shader und führt Berechnungen für Beleuchtung, Texturierung und Farbeffekte durch. Fragment Shader wird für jedes Pixel aufgerufen, was ihn zur ressourcenintensivsten Stufe der Grafikpipeline macht.
Wichtigste Erkenntnisse
Fragment Shader (Fragment- oder Pixelshader) ist eine programmierbare Stufe der Grafikpipeline, die die endgültige Farbe jedes Bildfragments berechnet. Ein Fragment ist ein potenzielles Pixel, das nach dem Bestehen von Tiefen- und Schablonentests zu einem sichtbaren Pixel auf dem Bildschirm wird.
Der Fragment Shader wird nach der Rasterisierung ausgeführt, wenn 3D-Primitive (Dreiecke) bereits in eine Menge von Fragmenten umgewandelt wurden. Der Shader empfängt interpolierte Attribute — Texturkoordinaten, Normalen, Farben, die im Vertex Shader für die Dreiecksscheitel berechnet und für jedes Pixel innerhalb des Dreiecks linear interpoliert wurden.
Vor dem Aufkommen programmierbarer Shader (vor DirectX 8 / OpenGL 2.0) wurde die Pixelfarbenberechnung von einer festen Pipeline mit einem begrenzten Satz von Operationen durchgeführt. Der programmierbare Fragment Shader erschien im Jahr 2001 und erweiterte die Grafikfähigkeiten radikal: Entwickler erhielten die vollständige Kontrolle über die Farbe jedes Pixels, was fotorealistische Beleuchtung, komplexe Materialien und Posteffekte ermöglichte.
Fragment Shader wird von der GPU für jedes vom Rasterisierer erzeugte Fragment gestartet. Jeder Shader-Aufruf verarbeitet ein Fragment, liest seine Eingabedaten, führt Benutzercode aus und schreibt den Ausgabewert — die Fragmentfarbe im RGBA-Format.
Die Eingabedaten des Fragment Shaders umfassen interpolierte Attribute vom Vertex Shader (Texturkoordinaten, Normalen, Farben), uniforme Variablen (Lichtquellen, Matrizen) und Textursampler. Die Ausgabedaten sind der Farbvektor (gl_FragColor in OpenGL ES 2.0 oder eine benutzerdefinierte Variable in ES 3.0), der in den Farbpuffer geschrieben wird.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 fragColor;
void main() {
fragColor = texture(uTexture, vTexCoord);
}
Fragment Shader ist für die visuelle Qualität des Bildes verantwortlich. Alle Effekte, die der Benutzer auf dem Bildschirm sieht — Farbe, Schatten, Reflexionen, Transparenz — werden in dieser Stufe der Grafikpipeline berechnet.
Die häufigste Operation ist das Abtasten einer Farbe aus einer Textur mittels interpolierter UV-Koordinaten. Sampler2D und die Funktion texture() ermöglichen es, die Pixelfarbe aus einem Texturatlas zu ermitteln. Die Filterung (bilinear, trilinear, anisotrop) wird über Sampler-Parameter gesteuert und beeinflusst die Bildschärfe bei verschiedenen Betrachtungswinkeln.
Das Phong-Beleuchtungsmodell wird im Fragment Shader pro Pixel berechnet und liefert glattere Glanzlichter als die Vertex-Beleuchtung (Gouraud-Shading). Die Phong-Beleuchtung umfasst drei Komponenten: Umgebungslicht (ambient), diffuse und spiegelnde Reflexion (specular).
// Fragment shader with Phong lighting
in vec3 vNormal;
in vec3 vPosition;
uniform vec3 uLightDir;
uniform vec3 uLightColor;
void main() {
vec3 norm = normalize(vNormal);
float diff = max(dot(norm, uLightDir), 0.0);
fragColor = vec4(uLightColor * diff, 1.0);
}
Der Fragment Shader ermöglicht die Nachbearbeitung: Farbkorrektur über Lookup-Tabellen (LUT), Weichzeichnen (blur), Glüheffekt (bloom) und Tonemapping für HDR-Rendering. All diese Effekte arbeiten auf Pixelebene und werden in Echtzeit ausgeführt.
Die Leistung des Fragment Shaders ist der Hauptfaktor, der die FPS in modernen mobilen Spielen begrenzt. Da der Shader für jedes Pixel aufgerufen wird, kann selbst eine geringfügige Erhöhung der Codekomplexität zu einem merklichen Abfall der Bildrate führen.
Für mobile GPUs (Qualcomm Adreno, ARM Mali) wird empfohlen: mediump precision für Float-Variablen verwenden, Texturabfragen kombinieren, Early-Z-Tests anwenden, um unsichtbare Fragmente vor der Shader-Ausführung zu verwerfen.
| Methode | Beschreibung | Gewinn |
|---|---|---|
| Mediump precision | 16-Bit-Genauigkeit statt 32-Bit | Bis zu 2x Geschwindigkeit |
| Early-Z | Tiefentest vor dem Shader | Weniger Aufrufe |
| Texture atlasing | Eine Textur statt mehrerer | Weniger Wechsel |
Beide Shader-Typen sind vom Entwickler programmierbar, arbeiten aber auf unterschiedlichen Pipelinestufen und lösen unterschiedliche Aufgaben. Fragment Shader ist aufgrund der Anzahl der Aufrufe wesentlich ressourcenintensiver.
| Parameter | Fragment Shader | Vertex Shader |
|---|---|---|
| Anzahl der Aufrufe | Millionen (Bildschirmauflösung) | Tausende (Anzahl der Scheitel) |
| Eingabedaten | Interpolierte Attribute | Scheitelattribute |
| Hauptfunktion | Berechnung der Fragmentfarbe | Geometrietransformation |
| Texturzugriff | Vollständig (mehrere Sampler) | Eingeschränkt |
| Leistungseinfluss | Hoch (abhängig von Auflösung) | Mäßig (abhängig von Geometrie) |
Fragment Shader kann einfach (Texturabfrage) oder komplex (mehrschichtige Beleuchtung) sein. Betrachten wir zwei praktische Beispiele: grundlegende Texturierung und ein Gradienteneffekt mit Zeit.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
in vec3 vColor;
uniform sampler2D uDiffuseMap;
out vec4 fragColor;
void main() {
vec4 texColor = texture(uDiffuseMap, vTexCoord);
fragColor = texColor * vec4(vColor, 1.0);
}
#include <metal_stdlib>
using namespace metal;
struct FragmentIn {
float2 texCoord;
float3 normal;
};
fragment float4
fragmentMain(FragmentIn in [[stage_in]],
texture2d<float> tex [[texture(0)]]) {
constexpr sampler s(filter = linear);
float4 color = tex.sample(s, in.texCoord);
return color;
}
Häufig gestellte Fragen
Fragment Shader ist ein Miniprogramm auf der GPU, das bestimmt, welche Farbe jedes Pixel auf dem Bildschirm hat. Wenn der Vertex Shader die Form des Objekts bestimmt, dann bestimmt der Fragment Shader, wie dieses Objekt aussieht — Textur, Beleuchtung, Farbe.
Fragment Shader wird für jedes Pixel auf dem Bildschirm aufgerufen. Auf einem Gerät mit einer Auflösung von 2532x1170 (iPhone) sind das fast 3 Millionen Aufrufe pro Frame. Bei 60 FPS wird der Shader 180 Millionen Mal pro Sekunde ausgeführt, was enorme Rechenleistung erfordert.
Im Fragment Shader werden implementiert: Texturierung, Beleuchtung (Phong, PBR), Schatten, Reflexionen, Brechungen, bloom, Tiefenschärfe, Farbkorrektur, LUT-Filter und prozedurale Texturgenerierung.
Verwenden Sie mediump precision für float, reduzieren Sie die Anzahl der Texturabfragen, wenden Sie Early-Z-Culling an, kombinieren Sie Shader-Operationen und vermeiden Sie bedingte Verzweigungen innerhalb des Shaders.
Es ist dasselbe. Der Begriff Fragment Shader wird in OpenGL / Vulkan verwendet, Pixel Shader in der Direct3D-Terminologie (Microsoft). Funktionell sind sie identisch: beide berechnen die Farbe jedes Fragments/Pixels.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch