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:
D11 hybrid-360P-montage
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:


← Monte Carlo Sampling | ● | Rendering Quality versus Speed →

Options: