Shaderanalyse mit CaradNext

 

In der neuesten Inkarnation von CaradNext ist eine IDE zur Bearbeitung von GLSL Shaderprogrammen hinzugekommen, wie diese zu bedienen ist, soll hier an einem Beispiel erläutert werden.

Was wird benötigt:

Die neuste Version von CaradNext
Das 3DLabs OpenGL GLSL Shading Language Demo Programm, um das Tutorial nachvollziehen zu können

Das Demo Programm ist an sich auch recht interessant, im Zuge dieses Tutorials werden allerdings nur dessen Ressourcen benötigt, da es vor allem darum geht, zu zeigen, wie bestehende Shader sehr einfach analysiert werden können.

Weiterhin wird eine Grafikkarte mit GLSL Unterstützung benötigt, also eine GeforceFx ab 5200, eine ATI Radeon ab 9500 oder auch eine 3DLabs WildCat Realizm, falls wirklich jemand Zugriff auf ein so leckeres Stück Hardware haben sollte.

Das Tutorial schließt mit der eigenständigen Erstellung einer kleinen Demo mit GLSL Shadern ab, die ungefähr so aussehen wird (Executable ist als Link hinter dem Bild hinterlegt).

Die Hauptprämisse bei der Erstellung der IDE war, dass bestehende Shader nicht nur neu erstellt, sondern aus allen möglichen Quellen möglichst leicht übernommen werden können - am Besten ohne dass der Anwender weiteres Wissen über die Interna der entsprechenden Shaderprogramme benötigt - vielmehr sollte es möglich sein, interaktiv mit Shadern zu experimentieren, um so

  1. ein besseres Verständnis der GLSL Shadersprache bzw. der entsprechenden OpenGL Schnittstelle zu erlangen
  2. auch als (Halb)Laie in der Lage zu sein bestehende Shader abzuändern und in eigene Programme einzubauen - selbstverständlich ist das Copyright von Shaderprogrammen ebenso zu beachten, wie das jeglichen anderen Sourcecodes, ein Werkzeug um die Trickkiste von "Professionellen" etwas zu durchleuchten, sollte jedoch durchaus nützlich sein.

Die Hauptanforderung eines solchen Werkzeuges ist, dass es mit dem Shadersource alleine auskommt, ohne zusätzliche Informationen darüber zu haben, welche Parameter fest verdrahtet in einem Programm übergeben werden, bzw. wie diese vorliegen. Dies ist mit GLSL und etwas Programmieraufwand allerdings möglich, da die OpenGL Schnittstelle zur Shaderprogrammierung recht auskunftfreudig ist, was wo und wie erwartet wird - das Kunststück war nur, das ganze in eine brauchbare Oberfläche zu packen.
Da keine Informationen darüber vorliegen, welcher Wertebereich für übergebene Parameter valide ist, wird dieser Wertebereich aus dem aktuellen Wert selbst geschätzt - dies funktioniert sogar recht gut, wenn man sich an die Bedienung der entsprechenden Steuerelemente gewöhnt hat (hierzu später etwas mehr).

Als erstes benötigen wir ein (oder mehrere) Objekte, die in Zukunft die erstellten Shader tragen sollen. Für unsere Demo gehen wir auf das MetaBall Primitive (Rechtsklick auf die Reiter im Primitivefenster, Auswahl: MetaBall), erstellen dort einen neuen MetaBall und fügen ihm drei Metaspheres hinzu, so wie auf dem Bild angegeben:

Da das Metaballfenster ziemlich viel Platz braucht, wählen wir danach ein anderes Primitivefenster, etwa einen Würfel, da wir später ohnehin noch einen solchen als Lichtquelle verwenden werden.

Tipp.: sollte beim Herumfuhrwerken mit den Fenstern in Carad Verwirrung entstehen, genügt meist ein Druck auf F11 um wieder brauchbare Ordnung herzustellen.

Mit einem Druck auf öffnen wir dann die IDE zur Bearbeitung von Shadern und laden dort aus dem Shaderverzeichnis der 3DLabs GLSL Demo (normalerweise Programme\3DLabs\GLSL Demo\shaders\default ):

  • die Datei gooch.vert als Vertexshader (Datei > Vertexshader öffnen > gooch.vert)
  • die Datei gooch.frag als Fragmentshader (Datei > Fragmentshader öffnen > gooch.frag)

Das Shaderfenster sollte nun ungefähr so aussehen:

Und wer Lust hat, kann schon mal ausprobieren, ob die beiden Shaderobjekte korrekt kompilieren würden (zumindest auf der GFFX tun sie es).

Damit Shaderobjekte tatsächlich angewandt werden können, müssen sie an ein sogenanntens Shaderprogramm gebunden und gelinkt werden. Aus diesem Grund erstellen wir einfach ein neues Shaderprogramm und ziehen beide Shaderobjekte darauf. Wer Lust hat kann das so erstellte Shaderprogramm ebenfalls linken, und die schöne Ausgabe des IDE Outputfensters bewundern :^).

Damit der Shader auf das Metaballobjekt angewandt wird, genügt es, das Shaderprogramm mit der Maus auf das entsprechende Objekt zu ziehen (im Objektfenster scheint es dann auch unter "gebundene Shader" auf) - allerdings schaut er noch wenig beeindruckend aus, was wir aber alsbald ändern wollen

Immerhin ergibt das Shaderprogramm bereits ein brauchbares specular Highlight auf einer schwarzen Oberfläche, was mit normaler OpenGL Beleuchtung schwierig machbar wäre. Nun kommt allerdings die starke Seite des Shadereditors - wir gehen bei aktiviertem Shaderprogramm auf das Fenster Uniforms

Und wählen dort "Variablen importieren". Carad versucht dann aus dem Shader selbst die verwendeten Uniformvariablen zu laden, und der BaseGraph internen Repräsentation eines Shaderprogrammes hinzuzufügen (wer sich unter dem vorigen Satz nichts vorstellen kann, vergesse ihn einfach). Diese Uniform Variablen werden dann dargestellt und können interaktiv über Editboxen und Scrollbars geändert werden, wobei für die Scrollbars folgendes gilt:
Es gibt kein Minimum und Maximum, vielmehr wird der aktuelle Wert nach seiner Größe verändert, sobald die Scrollbar verlassen (oder bei aktiver Scrollbar "Enter" gedrückt) wird, "schnellt" sie automatisch auf den Nullpunkt zurück. Spacebar setzt alle Scrollbars (und damit die damit verbundenen Uniformwerte) eines Parameters (etwa eines 3D-Vektors) auf den selben Wert.

Ockerfarbene Textboxen erwarten in Carad die Eingabe einer Funktion (auch andere Eingabefelder werten Funktionen aus, speichern dann aber nur das Ergebnis), die auch zur Laufzeit ausgeführt wird - in der Shader IDE wird man damit in einem der nächsten Releases Uniformwerte transformieren können, bevor sie an OpenGL gesandt werden (um z.B. triviale Berechnungen vom Vertex- oder Fragmentprozessor auf den Client auszulagern, wo sie sehr viel weniger "Prozessorpower" benötigen, da sie nur einmal ausgeführt werden anstatt per Vertex oder gar Fragment). In der akutellen Caradversion haben die ockerfarbenen Textboxen der GLSL IDE noch keine Funktion (immerhin werden Inhalte bereits gespeichert).

Insbesondere interessant ist die Fähigkeit Uniformwerte automatisch generieren zu lassen - dazu dienen die Buttons, die neben manchen Parametern angezeigt werden - je nach Typ einer Uniformvariable kann sie auf unterschiedliche Weise automatisch erzeugt werden. Im aktuellen Fall wird die Variable LightPosition der Objektposition des Objektes "Box" entnommen (dieses wurde vorher natürlich erstellt), womit dieses Objekt quasi zur Lichtquelle für diesen Shader wird.

Das Ergebnis sieht dann so aus:

Nun wollen wir aus der Szene noch ein kleines Demo machen, dies geht dank integrierter Skriptsprache relativ einfach: wir starten die BaseGraph Pascal IDE und geben folgendes kleine Programm ein:

Bedingung für die Funktion dieses Programmes ist, dass die automatische Benennung des Metaballobjektes beibehalten wurde. Die weitere Vorgehensweise ist einfach: entweder das Programm innerhalb von Carad starten, ein eigenständiges Programm mittels "Executable erstellen" im Menüpunkt Datei kreieren - oder aber, eine installiertes Delphi ab Version 4 vorausgesetzt, kann aus den bestehenden Informationen auch ein lauffähiges Delphiprogramm erstellt werden, das genau die Funktionalität bietet, die in BaseGraph Pascal programmiert wurde und in Delphi selbst weiter bearbeitet werden kann.

Notwendig ist dies allerdings nicht, da Carad (bzw. das integrierte BaseGraph Pascal) auch eigenständige .EXE Programme erstellen kann.

Der Umgang mit Texturen in Shadern ist übrigens ebenso einfach: die entsprechenden Uniformvariablen können im entsprechenden Fenster gesetzt werden, der Anwender hat dann mit der richtigen Kombination von TextureSettings und Texturen dafür zu sorgen, dass die entsprechenden Textureinheiten zum Zeitpunkt der Aktivierung des Shaders zur Verfügung stehen. An sich recht einfach - bei Nachfrage schreibe ich hierzu eventuell aber ein eigenes Tutorial (sollte aber nicht notwendig sein).

Selbstverständlich stehen auch die anderen Shader des 3DLabs GLSL Demos dem Experimentierdrang offen (bei manchen müssen noch die entsprechenden Texturen mitgeladen werden, die in einem anderen Verzeichnis liegen), selbstverständlich könnt ihr nun auch eigene Shader schreiben (oder von anderen Programmen übernehmen).

Ich hoffe, dass Carad und dieser Text dem einen oder anderen den Umgang mit Shadern erleichtern,
viel Spaß beim Programmieren,