Computergrafik
Monte Carlo Implementierung
← Monte Carlo Sampling | ● | Rendering Quality versus Speed →
Pseudo-Code fĂźr kombiniertes Ray-Tracing und Path-Tracing (stark vereinfacht):
# Maximal erlaubte Pfadtiefe
MAX_DEPTH = 10
function TracePath(ray, depth = 0):
intersection = FirstRayIntersection(ray)
# Basisfall 1: Strahl trifft nichts
if not intersection.hit:
return EnvironmentLight(ray)
# Basisfall 2: Strahl trifft direkt auf eine Flächen-Lichtquelle
if intersection.object is a light:
return intersection.emittedLight
intensity = 0
# Next Event Estimation (Direktes Licht z.B. von Punkt-Lichtquellen)
intensity = intensity + LightAmount(ray, intersection)
# Maximale Tiefe erreicht
if depth >= MAX_DEPTH:
return intensity
# Aktuelle Oberflächeneigenschaften
m = intersection.metallic
a = intersection.alpha
# Refraktierter Lichtpfad (Einfallswinkel > Ausfallswinkel)
nextRay.start = intersection.location
nextRay.direction = Refract(-ray.direction, intersection.surfaceNormal, intersection.IOR)
# Basisfall 3: Rekursiver Aufruf fßr Transmission (nicht-metallischer Oberflächen = Ray-Tracing)
if a < 1 and m < 1:
intensity = intensity + (1 - m) Ă (1 - a) Ă TracePath(nextRay, depth + 1)
# Reflektierter Lichtpfad (Einfallswinkel = Ausfallswinkel)
nextRay.direction = Reflect(-ray.direction, intersection.surfaceNormal)
# Gewichtung des reflektierten Lichts (fßr metallische Oberflächen mit Roughness=0)
w = Ď Ă intersection.BRDF(âray.direction, intersection.surfaceNormal, nextRay.direction) Ă a
# Basisfall 4: Rekursiver Aufruf fßr indirekte Beleuchtung (metallischer Oberflächen = Ray-Tracing)
if w != 0 and m > 0:
intensity = intensity + m Ă w Ă TracePath(nextRay, depth + 1)
# Russisches Roulette (Zufälliger Pfadabbruch)
q = TerminationProbability(intersection)
if random() < q:
return intensity
# Indirekter Lichtpfad (Zufälliges Sampling)
nextRay.direction = CosineWeightedSample(intersection.surfaceNormal)
# Gewichtung des indirekten Lichts (fßr nicht-metallische Oberflächen)
w = Ď Ă intersection.BRDF(âray.direction, intersection.surfaceNormal, nextRay.direction) / (1 - q) Ă a
# Basisfall 5: Rekursiver Aufruf fßr indirekte Beleuchtung (nicht-metallischer Oberflächen = Monte-Carlo Sampling)
if w != 0 and m < 1:
intensity = intensity + (1 - m) Ă w Ă TracePath(nextRay, depth + 1)
return intensity
Hinweis: die Werte von BRDF, intensity und w sind keine einfachen Skalarwerte sondern RGB-Farbvektoren.
Monte-Carlo Sampling:
obere Zeile: nicht-metallisch, roughness=1 (direkt, indirekt, kombiniert)
untere Zeile: 75% metallisch, roughness=0 (direkt, indirekt, kombiniert)
Literatur
Mehr zum Lesen fĂźr diejenigen, die es wirklich genau wissen wollen:
- https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function
- https://de.wikipedia.org/wiki/Lambertsches_Gesetz
- https://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models
- https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model
- https://pharr.org/matt/blog/2022/05/06/trowbridge-reitz
← Monte Carlo Sampling | ● | Rendering Quality versus Speed →