Shader 101: Grundlagen

„Mit Shadern kenne ich mich nicht aus“ sagen Einsteiger häufig und dabei sind Shader zumindest grundsätzlich alles andere als eine dunkle Zauberkunst, sondern einfache Programme, die auf der Grafikkarte laufen.

In diesem Artikel, den ich bei Interesse vielleicht sogar zu einer Shader-Tutorial-Serie ausbauen werde, möchte ich die Grundlagen der Shader erklären. Dabei werde ich mich auf HLSL und XNA beschränken. Trotzdem vermittelt dieser Artikel wichtige Informationen, die auch für andere Systeme als Basis dienen können, denn Shader funktionieren in allen Systemen sehr ähnlich.

Begrifflichkeiten

Zu Anfang möchte ich die Abkürzung HLSL etwas genauer erklären. Sie steht für High Level Shader Language was soviel bedeutet wie „Hochsprache für Shader“. Es ist also eine mehr oder weniger einfache Programmiersprache, die speziell für die Entwicklung von Shadern erfunden wurde. Vom Syntax her ähnelt sie C. Der Syntax ist nicht sonderlich kompliziert und auch für den Einsteiger leicht zu erlernen.

Diese Shader waren bei ihrer Einführung vor ein paar Jahren jedenfalls eine kleine Revolution. Sie sollten – was sie seit DirectX 10 auch getan haben – nach und nach die Fixed-Function-Pipeline ablösen. Die Fixed-Function-Pipeline war dabei im Grunde genommen eine fest verdrahtete Anordnung von Funktionen (Transformation, Beleuchtung, Nebel etc) die jeder Vertex und jeder Pixel durchlaufen musste um auf den Bildschirm zu gelangen. Durch Einsatz der Shader wurde es dem Entwickler jedoch möglich, darauf Einfluss zu nehmen und diese „Fixed-Functions“ durch eigene zu ersetzen.

Was sind denn dann GLSL- oder CG-Shader?

Im Grunde genommen handelt es sich bei beiden Sprachen um ähnliche Dinge wie HLSL. Fangen wir mit CG an. Diese Sprache ist praktisch die Gleiche, wie HLSL. CG wurde von NVidia gemeinsam mit Microsoft entwickelt und wird vom Compiler praktisch in HLSL oder GLSL übersetzt, so dass es sowohl für OpenGL, als auch für DirectX eingesetzt werden kann. Aufgrund des Entwicklers von CG ist durchaus davon auszugehen, dass dies für NVidia Grafikkarten besser funktioniert. Glücklicherweise hat Microsoft sich dazu entschlossen mit HLSL eine ähnliche, aber speziell für DirectX verwendete Shader-Sprache zu entwickeln. Dies Shader laufen sowohl unter DirectX, als auch unter XNA und sollten auch problemlos mit API’s wie SlimDX etc. funktionieren.

GLSL ist das Gegenstück aus der OpenGL-Welt.

Der Syntax aller drei Sprachen ähnelt sich stark. Unterschiede gibt es hauptsächlich im Detail. Man kann zwar nicht unbedingt eine Sprache direkt in eine andere übersetzen lassen, aber wenn man sich ein wenig damit auseinandersetzt, sollte es keine große Schwierigkeit sein, eine der Shader-Sprachen in eine andere zu übersetzen.

Arten von Shadern

Wichtig ist die Unterscheidung der Shader-Arten. Es gibt zwei, bzw. seit DirectX 10 und Shader Modell 4.0 drei Shader-Arten. Diese haben eine bestimmte, feste Aufgabe und diese feste Zuständigkeit ist auch einer der Gründe, warum Grafikkarten so schnell sind.

Eine CPU in einem modernen PC oder einer Konsole sind sehr schnell und haben eine Menge Rechenleistung. Im direkten Vergleich zu einer GPU sehen sie aber in der Regel sehr schlecht aus. Würde man versuchen auf der CPU Dreiecke zu transformieren, Texturen zu projizieren und Texel zu filtern, so würde man nur einen Bruchteil der Leistung erreichen, die eine GPU erreicht. Was ist nun der große Unterschied? Warum erreichen die CPU-Hersteller nicht die Leistungen, die die GPU-Hersteller erreichen? Sind sie schlechter? Und wenn ja, warum bringen die GPU-Hersteller nicht einfach schnelle CPU’s auf den Markt?

Diese Fragen sind relativ einfach zu beantworten. GPU’s sind hochoptimiert für spezielle Einsatzzwecke. Einsatzzwecke, die für die Berechnung und Darstellung von Grafik benötigt werden. Diese Dinge sind hochspezialisiert und entsprechend gut optimiert. Im Gegensatz dazu sind CPU’s Multitalente. Sie können sehr viele unterschiedliche Dinge und sind darin auch sehr gut. Ein häufiger Wechsel von Aufgaben, beidseitiges Streaming und Bearbeitung von Daten, Task-Switching, bedingte Ausführung sind Disziplinen, wo eine GPU nicht mit einer CPU mithalten kann. Eine GPU ist hochparallelisiert und kann Unmengen von gleichartigen Daten immer wieder auf die gleiche Art und Weise bearbeiten. Wenn es aber darum geht, viele unterschiedliche Dinge zu tun, so kann eine GPU nicht mehr Schritt halten.

Wieso passt dieser kleine Exkurs nun in den Abschnitt über die Shader-Arten? Das ist einfach zu erklären: Die Shader-Arten sind sehr spezialisierte Programme, wie wir im folgenden sehen werden. Es gibt relativ große Einschränkungen, dafür sind die Shader aber verdammt schnell.

Vertex-Shader

Der Vertex-Shader bearbeitet, wie der Name bereits vermuten lässt, Vertices. Die Betonung liegt hier auf bearbeitet, denn der Vertex-Shader ist nicht in der Lage Vertices zu erzeugen. Er kann nur bestehende Vertices verändern. Der Vertex-Shader wird dabei für jeden einzelnen Vertex exakt einmal ausgeführt.

Standardaufgabe des Vertex-Shaders ist es, die einzelnen Vertices zu projizieren, also aus dem World-Space in den Screen-Space zu transformieren. Kamera-Parameter wie die View- und Projektions-Matrizen werden in diesem Shader angewendet.

Pixel-Shader

Der Pixel-Shader arbeitet mit Pixeln und ist dafür verantwortlich die Farbe eines jeden Pixels zu bestimmen. Die Position eines Pixels kann dabei nicht verändert werden. Diese wird durch den Vertex-Shader festgelegt. Der Pixel-Shader wird für jeden einzelnen Pixel auf dem Bildschirm ausgeführt.

Der Pixel-Shader wird z.B. dafür verwendet, die Szene auf eine gewisse Distanz im Nebel verschwinden zu lassen oder um Per-Pixel-Lighting, also die Beleuchtungsberechnung jedes einzelnen Pixels, durchzuführen.

Geometrie-Shader

Dieser Shader ist eine Neuerung, die mit DirectX 10 eingeführt wurde und leider in XNA nicht verfügbar ist. Der Geometrie-Shader kann neue Geometrie erzeugen (Tesselierung). Man kann damit z.B. einen „Subsurf-Modifier“, wie er aus Blender bekannt ist, erzeugen um gebogene Flächen weicher erscheinen zu lassen. Man kann damit aber auch unterschiedliche LOD-Stufen generieren. Der Geometrie-Shader wird auf einzelne Dreiecke ausgeführt und kann dafür neue Geometrie erzeugen.

Wie man sieht, sind die Shader sehr spezialisiert. Es gibt aber auch ein Reihe weiterer Einschränkungen, die sich mit den sogeannten Shader-Level (eine Art Versionierung) auch noch verändert haben. Näheres zu den Einschränkungen findet ihr z.B. in der Wikipedia.

XNA unterstützt dabei ab Version 4.0 mit dem Reach-Profil Shader Modell 2.0 und mit dem HiDef-Profil Version 3.0. In XNA 3.1 gibt es diese Unterscheidung nicht und dies hängt unter anderem von der Grafikkarte ab (maximal aber Version 3.0).

Weiterführende Themen und Artikel

In diesem Abschnitt liste ich nach und nach weitere Artikel zum Thema auf, die ich bereits erstellt habe, bzw. zukünftig erarbeiten werde, so dass hier nach und nach eine möglichst vollständige Liste entstehen wird, die alle Themen rund um Shader erschlagen wird.

Shader 101: XNA FX-Files
Shader 101: Umgebungslicht / Ambient Light
Shader 101: Diffuse / Directional Light
Shader 101: AlphaText (clip)
Shader 101: Clip Planes

Advertisements

Veröffentlicht am 11.04.2011 in Grundlagen, Shader, XNA, XNA 3.1, XNA 4.0 und mit , , , , , , getaggt. Setze ein Lesezeichen auf den Permalink. 8 Kommentare.

  1. […]Fangen wir mit CG an. Diese Sprache ist praktisch die Gleiche, wie HLSL. Der Unterschied ist, daß CG von NVidia gemeinsam mit Microsoft entwickelt wurde und sich daher nur für NVidia-Grafikkarten eignet.[…]
    -> Das stimmt so weit ich weiß nicht ganz. CG Shader funktionieren auch auf ATI/AMD Grafikkarten. Jedenfalls tun sie es auf meiner ATI/AMD Grafikkarte 🙂

  2. Mal ne Frage aus reinem Interesse, kann man den Geometrie-Shader in dem ANX Framework verwenden?

    • Ja, ist theoretisch sehr einfach möglich, praktisch aber noch nicht eingebaut… Ich wäre aber bei einem Patch behilflich, hätten wir ja beide was von 😉

  1. Pingback: Shader 101: XNA FX-Files « "Mit ohne Haare"

  2. Pingback: Shader 101: Clip Planes « "Mit ohne Haare"

  3. Pingback: Shader 101: Diffuse / Directional Light « "Mit ohne Haare"

  4. Pingback: SpriteBatch Magic: Grundlagen « "Mit ohne Haare"

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: