ZFX
ZFX Neu
Home
Community
Neueste Posts
Chat
FAQ
IOTW
Tutorials
Bücher
zfxCON
ZFXCE
Mathlib
ASSIMP
NES
Wir über uns
Impressum
Regeln
Suchen
Mitgliederliste
Membername:
Passwort:
Besucher:
4440612
Jetzt (Chat):
52 (0)
Mitglieder:
5239
Themen:
24223
Nachrichten:
234554
Neuestes Mitglied:
-insane-
"ZFXMathLib" von Richard Schubert (Richard Schubert)


Hiho,

Wie sicherlich schon viele von euch bemerkt haben, wird zur Zeit von einigen von uns die ZFXMathlib aufgebaut.

Darunter befinden sich auch Tools zur Berechnung von Spherical Harmonic Functions, die ich hier vorstellen möchte um diese Technik (insbesondere die Beleuchtung mit diesen) ein wenig verständlicher zu gestalten. Oder besser, zu klären was sich eigentlich dahinter verbirgt.




Was mill man mit den Spherical Harmonics erreichen? Man möchte eine beliebig komplexe Beleuchtungsumgebung in Echtzeit auf ein Objekt anwenden. Diese Umgebung kann eine CubeMap und/oder Lichter sein, sodass man eine Art globale Beleuchtung erreichen kann. Jede dieser Umgebungen kann man als sphärische Funktion betrachten, sodass jeder Punkt auf einer Kugel einem Funktionswert entspricht der die Beleuchtungsstärke/-farbe beinhaltet.

So kann man ganz oben links im Bild die folgende Funktion sehen (darunter ist die gleiche Funktion auf eine Kugel projiziert mit dem Funktionswert als VertexFarbe):

float funcvalue = ( ( Max(0, 5 * Cos(theta) - 4) + Max(0, -4 * Sin(theta - PI) * Cos(phi - 2.5) - 3) ) * 1.3 );
wobei theta und phi den winkeln auf der kugel entsprechen

Sie ist schon relativ komplex und daher aufwändig zu berechnen, in einem Vertex Shader würde man Schwierigkeiten haben solch eine Beleuchtungsfunktion auswerten zu wollen.

Jetzt kommen die SHs zum Einsatz.
Mit ihnen ist man in der Lage sphärische Funktionen in einfache Vektoren (SH-Koeffizienten) zu komprimieren.
Umso mehr Koeffizienten man verwendet, desto genauer wird die Originalfunktion approximiert. Wenn man zum Beispiel SHs der 4.Ordnung verwendet, erhält man einen 16D-Vektor. Für unsere Funktion würde das in folgendem Resultat enden:

[ 0.39925,
-0.21075, 0.28687, 0.28277,
-0.31530, -0.00040, 0.13159, 0.00098, -0.09359,
-0.00072, 0.12290, 0.30458, -0.16427, -0.00062, -0.09126 ]

Mit diesen Werten haben wir also eine Annäherung an die oben gerzeigte sphärische Funktion. Oben rechts im Bild kann man sehen wie gut diese Approximation ist. Auf den ersten Blick nicht so toll, aber die Projektion auf der Kugel zeigt, dass es garnicht mal so schlecht ist. Die Kompression mit der 5.SH-Ordnung würde in diesem Fall schon zu einem fast perfektem Ergebnis führen, aber das wären dann schon 25 Koeffizienten.

Nun können wir eine beliebig komplexe sphärische Funktionen komprimieren, aber was bringt uns dass im Vertex Shader, wenn wir damit nun beleuchten wollen?
Man muss für jedes Vertex ebenfalls eine Beleuchtungsfunktion errechnen, nur dass diese Daten enthält von wo (Punkt auf der Kugel) in welcher Intensität Beleuchtung kommen kann (ist vollkommen unabhängig von der Beleuchtungsfunktion der späteren Umgebung), sozuagen eine Beleuchtungsmöglichkeitsfunktion. Diese projiziert man ebenfalls in SH-Koeffizienten der gleichen Ordnung wie die Kompression der echten Beleuchtungsfunktion und speichert diese in dem jeweiligem Vertex ab.

Schließlich hat man eine globale Beleuchtungsfunktion und pro Vertex eine Beleuchtungsmöglichkeitsfunktion. Beide liegen als SH-Koeffizienten-Vektoren vor, die man im Vertex Shader nurnoch verbinden braucht. Kurz, man bildet das Punktprodukt aus beiden Vektoren. So erhält man die Beleuchtung für das jeweilige Vertex.

Das klingt irgendwie statisch, was passiert wenn das beleuchtete Objekt rotiert? Man muss einen der beiden SH-Vektoren rotieren, da kommt natürlich nur die Beleuchtungsfunktion in Frage, denn für jedes vertex die ganzen Koeffizienten zu rotieren wäre doch ein wenig zu aufwändig. So rotiert man die Beleuchtungsfunktion "einfach" mit der inversen Worldmatrix des Meshes.

Der Teapot wird mit einer SH-komprimierten CUbe Map beleuchtet, die normalerweise nicht direkt zur Beleuchtung verwendet werden könnte. So wurde diese auch erst in eine sphärische Funktion konvertiert um sie dann in SH-Koeffizienten approximieren zu können.

Man kann gut erkennen wie der Knauf des Teapots einen sehr weichen Schatten wirft.
Das Ganze sieht mit rotierendem Licht am besten aus.
Da es nicht ganz so einfach ist Interreflection mit Hilfe der GPU zu berechnen, habe ich dies noch nicht implementiert, sonst würden die gelb beleuchteten Vertices unter dem Knauf noch heller sein.

Das ganze kann man natürlich auch auf Pixelebene machen um eventuelle Ungenauigkeiten zu vermeiden oder das Highpoly-zu-Lowpolyverfahren auch für SHs anzuwenden. Das würde bei dieser Approximationsstufe aber schon in vier Texturen resultieren, was sicherlich noch nicht sehr speicherfreundlich ist. Zusätzlich muss das Mesh über Unique Texturing verfügen, was meistens zu weiteren Einschränkungen führt.

Den Diffuseanteil von direktionalen Lichtern und teilweise auch Punktlichtern kann man so in beliebiger Anzahl in die Beleuchtungsfunktion hineinaddieren ohne dass sich etwas im Shader ändert.

Den kompletten Quellcode gibt's später wenn die ZFXMathLib und die Samples ausgereift sind.

Download: SH Samples

weiterführende Links:

Robin Green
Don Williamson
Peter-Pike Sloan
Tom Forsyth




Wer Lust hat an der ZFXMathlib mitzuwirken, ist jederzeit willkommen und kann sich hier melden.







Von ChrisM am 09.08.2004, 23:40:09 Uhr
*daumenhoch*! Endlich mal was Anderes (und zudem noch was, um das ich bisher immer ein riesigen Bogen gemacht habe).

Ich werde mir die Papers mal näher anschauen, deine Beschreibung klingt schon interessant. :)

Auf das Programm (bzw. die Shader) bin ich auch schonmal gespannt!

Von Peter Müller am 09.08.2004, 23:48:50 Uhr
DoxyGen Dokumentation, gut gemacht, schau mir grad alles an.

Von Richard Schubert am 10.08.2004, 07:21:00 Uhr

da die shader in fxfiles sind, liegen diese dem Sample Download bei. :D

Von Reita am 10.08.2004, 08:29:45 Uhr
Danke für die umfassende, aber trotzdem leicht zu verstehende Erklärung von SHs: Ich wollte mich schon öfters damit beschäftigen bin aber irgendwie immer durch zeilenlange mathematische Formeln abgeschreckt worden ...

Die Samples werd ich mir gleich herunterladen, hoffentlich laufen sie auf meinem Rechner.

Von Kimmi am 10.08.2004, 08:37:13 Uhr
Zwar durfte ich es vorher schon mal sehen, trotzdem da berechtigterweise *Daumennachobeheb*.

MfG Kimmi

Von Mr.DX am 10.08.2004, 09:39:07 Uhr
Super, wirklich gut.
Kann es sein, das die Samples mit der neusten DX-Version kompiliert wurden? Bei mir meckert er wegen der Version rum. Muss wohl mal das DX updaten.

Von Richard Schubert am 10.08.2004, 09:53:02 Uhr
natürlich sind diese mit dem neusten SDK kompiliert :D
hatte nur leider vergessen es im text zu vermerken.

Von Tales am 10.08.2004, 17:09:13 Uhr
Nun, eigentlich habe ich nach joydees Screenshots SH als etwas fieses gesehen, aber eigentlich sind es nur vorberechnete Lichtwerte einer Kugel, pojeziert auf ein anderes Objekt, die auch eine Veränderung der Einfallsrichtung auf das Objekt erlauben?

jedenfalls siehts gut aus, meiner Meinung nach sogar besser als die originale Lichtberechnung.

Von Richard Schubert am 11.08.2004, 10:45:57 Uhr
Zitat:
Nun, eigentlich habe ich nach joydees Screenshots SH als etwas fieses gesehen, aber eigentlich sind es nur vorberechnete Lichtwerte einer Kugel, pojeziert auf ein anderes Objekt, die auch eine Veränderung der Einfallsrichtung auf das Objekt erlauben?


ähhm.. ja..

Zitat:

jedenfalls siehts gut aus, meiner Meinung nach sogar besser als die originale Lichtberechnung.

welche originale lichtberechnung? n dot l ist diesem lcihtmodel klar unterlegen, aber die echte funktion mit dem gleichen ergebnis ohne SH wäre nicht echtzeittauglich.