Raytracing / Pathtracing / Photon Mapping - Tutorial


  • Mod

    Habs noch nich durchgelesen, aber danke dass du dir die ganze muehe gemacht hast so ein detailiertes tutorial niederzuschreiben! habs gepinnt.



  • Aufgrund des Wunsches eines einzelnen Herren habe ich jetzt noch Lighttracing hinzugefügt. Ich habe wieder die Cornell-Box-Szene genommen und dabei versucht so minimal wie möglich alles zu halten. Kein Threading/Keine KD-Bäume.

    https://github.com/XMAMan/RaytracingTutorials/tree/master/07_Lighttracing

    https://github.com/XMAMan/RaytracingTutorials/blob/master/07_Lighttracing/RaytracingTutorials/Lighttracing.cs

    https://github.com/XMAMan/RaytracingTutorials/blob/master/07_Lighttracing/Images/Lighttracing.png

    Hier ist der Grundgedanke, dass man von der Kamera lauter Photonen aussendet und jedes mal, wenn ein Photon auf eine diffuse Fläche trifft, dann verbindet man den Punkt mit der Kamera und erstellt somit eine Menge von Pfadpunkten, welche von der Camera bis zur Lichtquelle reichen.



  • Da ich heute mal etwas Zeit habe, habe ich jetzt noch ein Pathtracer mit Next Event Estimation hinzugefügt. Dieser ist meiner Meinung nach der effektivste Algorithmus, wenn man neben dem Bildrauschen auch noch die Quellcode-Anzahl mit in Betracht zieht. Obwohl der Algorithmus nur so klein ist, erzeugt er trotzdem weitaus bessere Ergebnisse als der normale Pathtracer.

    Grundidee ist hier: Man erzeugt zufällige Pfade zwischen Camera und Lichtquelle, indem man einerseits das normale Pathtracing verwendet und anderseits verwendet man LightSource-Sampling, welches auch schon beim Berechnen des Direkten Lichtes beim Photonmapping verwendet wurde. Nur dieses mal nimmt man das LightSourcesampling nicht nur für den ersten Punkt, den die Kamera sieht sondern für alle Punkte, den der Pathtracer erzeugt.

    Ich habe also zwei Sampler zur Berechnung eines Farbwertes für ein Pixel: Brdf-Sampling und Lightsource-Sampling. Jeder Sampler erzeugt ein zufälligen Schätzwert für die Lichtmenge, die ein Pixel empfängt.

    Ich bezeichne die beiden Farbwerte, welche mit die beiden Sampler für ein Pixel erzeugen jetzt mal mit f1 und f2. Die endgültige Pixel-Farbe könnte ich nun z.B: so berechnen:

    f = (f1 + f2)/2.

    Das wäre einfach nur der Durchschnittswert von Beiden. Dieses Idee würde zwar funktionieren aber sie erzeugt unnötig hohes Bildrauschen.

    Eine bessere Idee ist der Einsatz von Multiple Importance Sampling. Dort gibt erzeugt man ein MIS-Faktor, welcher als Gewicht dient. Dieser Gewichtsfaktor ist eine Zahl zwischen 0 und 1 und gibt an, zu wie viel Prozent man das ein oder das andere Sampling-Verfahren in die Summe einfließen läßt. Unsere Formel sieht nun so aus:

    f = (1-MIS) * f1 + MIS * f2

    Dieser MIS-Faktor wird dadurch berechnet, indem man die Wahrscheinlichkeitsdichte im Bezug zum Flächenmaß (Pdf with Respect to Surface Area = PdfA) verwendet. Dieses PdfA ist eine Funktion, welche für einen konkret gesampelten Pfad P angibt, wie hoch die Wahrscheinlichkeit ist, dass genau dieser Pfad erzeugt wurde. Ich verwende hier Brdf- und LightSource-Sampling. Also habe ich für jedes dieser beiden Sampling-Verfahren auch eine zugehörige PdfA-Funktion:

    Brdf-PdfA(P)
    LightSampling-PdfA(P)

    Diese Funktionen bekommen ein Pfad (Menge von Punkten) als Input und sagen dann: Wie groß ist die Wahrscheinlichkeit, dass ich den Pfad P mit Brdf/Light-Sampling erzeuge?

    Ich verwende nun also zwei Sampler und jeder dieser Sampler erzeugt mir jeweils ein Pfad. Brdf-Sampling erzeugt mir den Pfad P1 und LightSourceSampling den Pfad P2.

    Der Farbwert(Radiance) für die Pfade wird PathContribution genannt und wird über die PathContribution-Funktion berechnet. Also Contribut(P1) und Contribut(P2).

    Jeder dieser beiden PathContribution-Werte muss nun mit den MIS-Factor gewichtet werden:

    PixelColor = MIS1 * Contribut(P1) / Brdf-PdfA(P1) + MIS2 * Contribut(P2) / LightSampling-PdfA(P2)

    Ich berechne MIS1 nun über folgende Formel, wenn ich davon ausgehe, dass P1 mit BrdfSampling erzeugt wurde:

    MIS1 = Brdf-PdfA(P1) / (Brdf-PdfA(P1) + LightSampling-PdfA(P1))

    Bei MIS2 gehe ich davon aus, dass P2 mit LightSampling erzeugt wurde.

    MIS2 = LightSampling-PdfA(P2) / (Brdf-PdfA(P2) + LightSampling-PdfA(P2))

    Die Idee von Multiple Importance Sampling ist also, dass man den Sampling-Verfahren mehr Gewicht verleiht, welche eine größere PdfA haben da großer PdfA-Wert wenig Rauschen bedeutet.

    Diese Formel (PixelColor=...), wo die Mis-Gewichtet Summe von mehreren Verfahren gebildet wird, nennt sich Secondary-Estimator.

    Der Primary-Estimator ist dann die Durchschnittswert von N Secondary-Estimator-Werten. Dieser Wert ist es dann, welcher am Ende in die Bilddatei geschrieben wird.

    Der Quelltext für dieses Pathtracing, wo Brdf-Sampling mit Lightsource-Sampling via Multipe Importance Sampling (MIS) vereint, gezeigt wird, habe ich hier:

    https://github.com/XMAMan/RaytracingTutorials/blob/master/08_PathtracingNextEventEstimation/RaytracingTutorials/PathtracingNEE.cs

    Hinweis: Wenn die PathContribution-Funktion den Wert 0 liefert, dann mache ich mir garnicht erst die Mühe das zugewhörige MIS-Gewicht zu bilden.

    Ausgabebild:
    https://github.com/XMAMan/RaytracingTutorials/blob/master/08_PathtracingNextEventEstimation/Images/PathtracingWithNextEventEstimation.png

    Um das ganze besser zu verstehen, wäre ein Blick in die Dissertation von Eric Veach hilfreich. Er setzt aber vorraus, dass man den Begriff 'Wahrscheinlichkeitsdichte im Bezug zu ein Maß' kennt. Ich denke, dass wäre mal ein eigenes Thema, was ich mal gesondert erklären müsste, wenn Bedarf besteht^^


Anmelden zum Antworten