Beschreibung

In dieser Exercise geht es darum einen Volumenrenderer zu vervollständigen. Dies ist der letzte Punkt in der Visualisierungs-Pipeline:

Exercise 3

Als Ausgangspunkt für das Volumenrendering dient das Volumen welches in Exercise 1 erstellt wurde. Es enthält neben den Datenwerten auch den Gradienten, welcher im Laufe dieses Beispiels für das korrekte Rendering benötigt wird.

Der Grund weshalb man Volumenrendering verwendet ist, dass es einen Datensatz in seiner Gesamtheit besser verstehen kann. Im Gegensatz dazu zeigen die 2D Ansichten der Daten nur Slices durch den Datensatz. In diesen kann man zwar einzelne Schichten genau analysieren, jedoch ist es sehr schwierig sich vorzustellen wie der gesamte Datensatz aussieht. Beim Volumenrendering kann man durch die Möglichkeit Bereiche transparent oder halb-transparent darzustellen einen Bezug zwischen den einzelnen Bereichen der Daten herzustellen.

Um die Darstellung zu kontrollieren, spielt in diesem Beispiel auch die Transfer Funktion eine wesentliche Rolle. Sie bestimmt mit welcher Farbe/Opazität ein bestimmter Datenwert dargestellt wird. Durch die Manipulation der Transfer Funktion können bestimmte Teile der Daten halb-transparent dargestellt werden oder auch komplett ausgeblendet werden. Damit ist es möglich die volumetrischen Daten genauer zu untersuchen.

Als Rendering Technik zum Volumenrendering soll in diesem Beispiel das Raycasting implementiert werden. Es ist zurzeit die am meisten verwendete Volumenrendering-Technik, da sie sehr einfach im Fragment Shader implementiert werden kann und auch viel Flexibilität bietet. In den einzelnen Tasks zu diesem Beispiel werden schrittweise die für das Raycasting notwendigen Schritte implementiert.

Zur Architektur des Plugins:

Ähnlich wie bei Exercise 2 werden auch hier die Shader für die Implementierung benutzt. Der Source Code des Plugins besteht aus einer RendererVisLabVolumeExercise.cpp und RendererVisLabVolumeExercise.h Datei sowie 3 GLSL Dateien welche den Shader Code enthalten. In C++ wird alles für das Rendering geladen und an die Grafikkarte weitergegeben. Es werden für das Raycasting auch schon die Start- und Endpunkte der Rays berechnet. Für die Tasks in dieser Exercise sind keine Änderungen in diesen Dateien vorzunehmen.

Von den 3 Shader Dateien ist nur plugin_renderer_vislabvolumeexercise_volume.glsl für die Exercise relevant. Die anderen beiden Shader Codes dienen dazu die Eintritts- und Austrittspunkte der Rays auf der Grafikkarte zu ermitteln. Als Startpunkt für die Implementierung der Aufgaben sollte man bei der main-Methode im plugin_renderer_vislabvolumeexercise_volume.glsl starten. Von hier werden alle anderen Methoden des Shaders aufgerufen. Die Parameter welche im GUI verändert werden können werden auch bereits an die vordefinierten Variablen im Shader übergeben. Der Shader Code an sich ist mit vielen Kommentaren versehen, um das Verständnis zu erleichtern.

Programmieraufgaben

TODO Beschreibung
1
Implement standard direct volume rendering
Implementiere direktes Volumenrendering (DVR: Direct Volume Rendering) mittels Alpha-Compositing und dem Over-Operator (siehe http://en.wikipedia.org/wiki/Alpha_compositing). In der Referenzlösung verwenden wir übrigens Front-To-Back Compositing.
2
Peform opacity correction:
Beim Raycasting beeinflusst der Abstand der Sample Punkte (Schrittweite) die Qualität der Resultate erheblich. Je kleiner der Abstand zwischen zwei aufeinander folgender Sample-Punkte entlang des Strahls desto besser ist der Ergebnis. Bei einer großen Schrittweite werden Artefakte sichtbar. Die Ursache dafür ist dass wir beim Raycasting im Wesentlichen eine numerische Integration durchführen. Jedoch wollen wir für verschiedene Schrittweiten dass das Volumen mit derselben Opazität erscheint. Bei einer größeren Schrittweite wird entlang des Strahls weniger Opazität akkumuliert. Daher erscheint das Volumen auch transparenter als bei einer kleineren Schrittweite. Aus diesem Grund ist es notwendig eine Korrektur der Opazität basierend auf der Schrittweite durchzuführen.
In der Implementierung wird die Schrittweite mittels der Variable fSampleDistance als Uniform Parameter an den Shader übergeben. Die Transfer Funktion ist definiert für eine Schrittweite von 1.0. Wenn die Schrittweite kleiner wird muss die Opazität daher reduziert werden. Bei einer größeren Schrittweite muss die Opazität dementsprechend erhöht werden. Die Details zur Berechnung der Opazitäts-Korrektur können im Kapitel 2.2 im Paper von Schulze et al. gefunden werden: http://www.calit2.net/~jschulze/publications/Schulze03b.pdf.
In diesem Paper finden Sie die Formel für die Korrektur der Opazität (erste Formel auf der Seite 3). Es ist übrigens nicht notwendig einen Lookup-Table zu erzeugen -- es genügt die Korrektur der Opazität direkt am Alpha-Wert des Sample-Punkts aus der Transfer Funktion durchzuführen.
3
Implement Blinn-Phong Shading
Eine gute Möglichkeit um die Visualisierung zu verbessern, ist das Gradient-Based Shading. Zur Berechnung des Shadings verwenden wir den Gradientenvektor als Oberflächennormale an der Stelle des Sample-Punkts. Mittels der Oberflächennormale kann das Blinn-Phong Shading durchgeführt werden (siehe http://en.wikipedia.org/wiki/Phong_reflection_model). Die Implementierung sollte folgende Parameter zur Beeinflussung des Shadings inkludieren:
  • Shading Intensität (uniform parameter fShadingIntensity): Dieser Wert beeinflusst die Stärke des Shadings (zwischen null und eins). Null bedeutet dass kein Shading durchgeführt wird und eins bedeutet dass volles Shading verwendet wird. In der Implementierung kann einfach zwischen dem Farbwert vom Shading und dem Farbwert ohne Shading implementiert werden.
  • Diffuses Shading (uniform parameter fDiffuseShading): Kontrolliert den diffusen Anteil beim Shading (zwischen null und eins, null bedeutet kein diffuser Anteil).
  • Specular Shading (uniform parameter fSpecularShading): Kontrolliert den spiegelnden (specular) Anteil beim Shading (zwischen null und eins, null bedeutet kein spiegelnder Anteil).
  • Specular Exponent (uniform parameter fSpecularExponent): Der Exponent welcher für den spiegelnden Anteil in der Shading Formel verwendet wird (je höher dieser Wert ist desto kleiner wird der Glanzpunkt und desto glänzender/spiegelnder erscheint die Oberfläche).
Die Argumente der Funktion in welcher das Shading implementiert werden soll sind der Farbwert aus der Transfer Funktion (vecColor), der Lichtvektor (vecLight), der normalisierte Gradientenvektor (vecGradient) und der Gradientenbetrag (fMagnitude).
4
Implement Gradient-Magnitude Shading Modulation
Da es nicht viel Sinn macht ein Shading bei einem sehr kleinen Gradientenbetrag durchzuführen (z.B. in Regionen in denen der Datenwert konstant ist), gibt es die Möglichkeit die Länge des Gradientens zu verwenden um den Einfluss des Shadings zu beeinflussen. Bei einem kleinen Gradientenbetrag sollte weniger Shading verwendet werden als bei einem großen Gradientenbetrag. Um diesen Effekt zu steuern gibt es im GUI einen Parameter Gradient Shading welcher als fGradientShading (uniform variable) an den Shader geschickt wird. Der Parameter sollte nach der Implementierung dieses Task folgende Auswirkung auf die Visualisierung haben:
Wenn der Wert null ist, soll das Shading nur auf Sample Punkte mit dem höchsten Gradientenbetrag angewendet werden. Wenn der Wert eins ist, soll das Shading auf alle Sample Punkte angewendet werden. Zwischen diesen Extrema soll ein gleichmäßiger Übergang implementiert werden (mittels Interpolation mit dem GLSL-Befehl smoothstep zwischen dem Farbwert mit und ohne Shading).
5
Implement Gradient-Magnitude Opacity Modulation
Als Alternative zum vorherigen Schritt kann auch die Opazität basierend auf dem Gradientenbetrag angepasst werden. Das bedeutet dass konstante Regionen transparent werden und Übergangsbereiche eine hohe Opazität haben. Dadurch werden Übergangsbereiche visuell hervorgehoben. Zur Steuerung dieser Modulation steht im GUI ein Parameter namens Gradient Opacity zur Verfügung. Der Wert dieses Parameters wird an die Variable fGradientOpacity im Shader weitergegeben. Die Modulation sollte ähnlich wie im Task zuvor funktionieren:
Wenn der Wert null ist sollen nur Sample Punkte mit hohem Gradientenbetrag sichtbar sein. Bei einem Wert von eins hat der Gradientenbetrag gar keinen Einfluss auf die Transparenz von Sample Punkten. Zwischen diesen Werten sollte wieder ein gleichmäßiger Übergang implementiert werden (Interpolation mit dem GLSL-Befehl smoothstep und anschließender Multiplikation mit dem Alpha-Wert des Sample Punkts).
Für weitere Details siehe das Paper von Levoy:
http://graphics.stanford.edu/papers/volume-cga88/
BONUS
Implement an Advanced Volume Rendering Technique
Sei kreativ! Implementiere deine eigene Visualisierungstechnik für Zusatzpunkte! Beachte dabei das Ziel deiner Visualisierungstechnik (welche Aspekte der Daten werden hervorgehoben?). Im GUI stehen drei verschiedene Optionen (Custom 1, Custom 2 und Custom 3) zur Verfügung. Im Shader Code kann für jede dieser Optionen eine eigene Visualisierungstechnik implementieren. Zur möglichen Manipulation der Visualisierungstechnik steht für jede Option ein Parameter (im Shader fCustom1, fCustom2 bzw. fCustom3) mit den Werten zwischen 0 und 1 zur Verfügung.
Hier sind einige Inspirationsquellen (es kann eine dieser Methoden implementiert werden, aber es sind natürlich auch Variationen dieser möglich und erwünscht):

User Interface

Folgende GUI-Parameter stehen zur Verfügung um das Volume-Rendering zu beeinflussen:

Name Effekt Zeigt Auswirkungen
Transfer Function Die Transferfunktion dient dazu Datenwerte auf optische Eigenschaften (Farbe und Opacity) abzubilden. Sie wird verwendet um bestimmte Wertebereiche der Daten auszublenden oder hervorzuheben. Mit unterschiedlichen Farben ist es auch möglich verschiedene Teile der Daten voneinander zu unterscheiden. ab TODO 1
Sample Distance Gibt den Abstand zwischen zwei Sample Punkten entlang des Strahls beim Raycasting an. Je kleiner der Wert desto besser ist die Renderingqualität aber auch desto länger dauert das Rendering. ab TODO 1
Technique Hier kann zwischen verschiedenen Rendering Techniken gewechselt werden. MIP ist standardmäßig schon in der Exercise implementiert. Die anderen Techniken sind selber zu implementieren. immer
Shading Mit dieser Option kann das Shading aktiviert oder deaktiviert werden. ab TODO 3
Shading Intensity Wie stark die Beleuchtungssituation das Volumenrendering beeinflusst (0 = nur Farben, 1 = maximales Shading) ab TODO 3
Diffuse Shading Diffuse Komponente des Beleuchtungsmodels
(Details siehe hier)
ab TODO 3
Specular Shading Spiegelnde Komponente des Beleuchtungsmodels
(Details siehe hier)
ab TODO 3
Specular Exponent Glattheit des Materials, beeinflusst die spiegelnde Reflexion
(Details siehe hier)
ab TODO 3
Gradient Shading Dieser Wert reguliert das Shading basierend auf den Gradientenwert (1 = Shading wird immer angewendet, auch wenn der Gradientenbetrag 0 ist; 0 = Shading wird nie angewendet, auch wenn der Gradientenbetrag 1 ist) ab TODO 4
Gradient Opacity Mit diesem Wert kann man die Opacity basierend auf den Gradientenbetrag regulieren (1 = Opacity wird duch den Gradienten nicht beeinflusst; 0 = Gradientenbetrag hat maximalen Einfluss auf die Opacity (je kleiner der Gradientenbetrag desto kleiner die Opacity)) ab TODO 5
Custom [1|2|3] Dieser Parameter kann verwendet werden um die in der Bonusaufgabe implementierte Visualisierungstechnik zu manipulieren. Der Wert kann zwischen 0 und 1 variiert werden. Im Shader kann auf die Variablen mit fCustom1, fCustom2 und fCustom3 zugegriffen werden. BONUS