Beschreibung
In dieser Exercise geht es darum einen Volumenrenderer zu vervollständigen. Dies ist der letzte Punkt in der Visualisierungs-Pipeline:
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.
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.
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:
|
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 |