Steuerungstasten

nächste Folie (auch Enter oder Spacebar).
vorherige Folie
 d  schaltet das Zeichnen auf Folien ein/aus
 p  wechselt zwischen Druck- und Präsentationsansicht
CTRL  +  vergrößert die Folien
CTRL  -  verkleinert die Folien
CTRL  0  setzt die Größenänderung zurück

Das Weiterschalten der Folien kann ebenfalls durch das Klicken auf den rechten bzw. linken Folienrand erfolgen.

Notation

Typ Schriftart Beispiele
Variablen (Skalare) kursiv $a, b, x, y$
Funktionen aufrecht $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$
Vektoren fett, Elemente zeilenweise $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$
Matrizen Schreibmaschine $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$
Mengen kalligrafisch $\mathcal{A}, \{a, b\} \in \mathcal{B}$
Zahlenbereiche, Koordinatenräume doppelt gestrichen $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$

Ziel: Lösen der Rendering-Gleichung

  • Die Rendering-Gleichung berechnet die reflektierte Strahldichte $L_o(\mathbf{v})$ im Oberflächenpunkt $\mathbf{x}$ mit Normale $\mathbf{n}$ in Richtung $\mathbf{v}$ durch Integration über die Anteile aller eingehenden Strahldichten $L_i(\mathbf{l})$ der Hemisphäre über der Oberfläche

    $L_o(\mathbf{v}) = L_e(\mathbf{v}) + \int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \, \underbrace{L_i(\mathbf{l}) \cos(\theta) \, d\omega}_{dE(\mathbf{l})}$

render_eqn
$\mathbf{x}$
$\theta$
$L_i(\mathbf{l})$
$L_o(\mathbf{v})$
$\Omega$
$\mathbf{n}$
  • $L_o(\mathbf{v})$ ausgehende Strahldichte
  • $L_e(\mathbf{v})$ ist die von der Fläche selbst emittierte Strahldichte
  • $L_i(\mathbf{l})$ eingehende Strahldichte
  • $E(\mathbf{l})$ Bestrahlungsstärke
  • $\mathrm{f}_r(\mathbf{v}, \mathbf{l})$ ist die sogenannte "Bidirectional Reflection Distribution Function" (BRDF)
  • $\Omega$ ist Gesamtheit aller Winkel der Hemisphäre über der Oberfläche

Auswerten den Rendering-Gleichung

  • Die Approximation der Rendering-Gleichung mit der Riemann-Summe ergibt:
    $\begin{align}L_o(\mathbf{v}) &= L_e(\mathbf{v}) + \int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, L_i(\mathbf{l}) \cos(\theta) \, d\omega\\ &= L_e(\mathbf{v}) + \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi/2} \mathrm{f}_r(\mathbf{v}, \mathbf{l})\,L_i(\mathbf{l}) \cos(\theta) \sin(\theta) \, d\theta \, d\phi\\ &\approx L_e(\mathbf{v}) + \sum\limits_{1}^{K}\, \sum\limits_{1}^{J} \mathrm{f}_r(\mathbf{v}, \mathbf{l})\,L_i(\mathbf{l}) \cos(\theta) \sin(\theta) \underbrace{\Delta\theta}_{\frac{\pi/2}{J}} \, \underbrace{\Delta\phi}_{\frac{2\pi}{K}}\\ &= L_e(\mathbf{v}) + \frac{\pi^2}{K\,J} \sum\limits_{1}^{K}\, \sum\limits_{1}^{J} \mathrm{f}_r(\mathbf{v}, \mathbf{l})\,L_i(\mathbf{l}) \cos(\theta) \sin(\theta) \end{align}$

Auswerten der Rendering-Gleichung bei diffuser BRDF

  • Als Beispiel soll nun die Rendering Gleichung mit einem Path Tracer ausgewertet werden
  • Dabei soll zunächt eine perfekt diffuse BRDF betrachtet werden
    $\mathrm{f}_r(\mathbf{v}, \mathbf{l}) = k_d$
  • Aus der Bedingung für die Energieerhaltung ergibt sich:
    $\begin{align}\int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \cos(\theta) d\omega = \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi/2} k_d \cos(\theta) \sin(\theta) \, d\theta \, d\phi &= k_d \,2\pi \, \Bigg[\frac{-\cos^2(\theta)}{2}\Bigg]_{0}^{\pi/2} \\ &= k_d \, \pi = \rho_d \end{align}$
  • Mit $\rho_d ≤ 1$ ist die Bedingung der Energieerhaltung erfüllt:
    $\mathrm{f}_r(\mathbf{v}, \mathbf{l}) = \frac{\rho_d}{\pi}\quad$ mit $\quad\rho_d \in [0, 1]$
  • Damit ergibt sich:
    $L_o(\mathbf{v}) \approx L_e(\mathbf{v}) + \rho_d \frac{\pi}{K\,J} \sum\limits_{1}^{K}\, \sum\limits_{1}^{J} L_i(\mathbf{l}) \cos(\theta) \sin(\theta)$

Beispiel: Brute-Force Auswerten der Rendering-Gleichung

example_emissivesphere

Beispiel: Brute-Force Auswerten der Rendering-Gleichung

struct RayPayloadType {
  vec3 radiance;
  vec3 nextRayOrigin;
  vec3 nextRayDirection;
  vec3 nextFactor;
  int level;
}; // type of the "payload" variable

...

void main() { /**** RAY GENERATION SHADER ****/

  // compute random pixel offset
  vec2 pixelOffset = hammersley(uint(frameID), uint(frameSize));
  
  // compute the texture coordinate for the output image in range [0.0, 1.0]
  vec2 texCoord = (vec2(gl_LaunchIDEXT.xy) + pixelOffset) / vec2(gl_LaunchSizeEXT.xy);

  // camera parameter
  float aspect = float(gl_LaunchSizeEXT.x) / float(gl_LaunchSizeEXT.y);
  vec3 rayOrigin = camPos;
  vec3 rayDirection = getCameraRayLookAt(30.0, aspect, camPos, camLookAt, camUp, texCoord);
  
  uint rayFlags = gl_RayFlagsNoneEXT; // no ray flags
  float rayMin = 0.001; // minimum ray distance for a hit
  float rayMax = 10000.0; // maximum ray distance for a hit  
  uint cullMask = 0xFFu; // no culling
  
  // init ray and payload
  payload.nextRayOrigin = rayOrigin;
  payload.nextRayDirection = rayDirection;
  payload.nextFactor = vec3(1.0);
  vec3 contribution = vec3(1.0);
  vec3 color = vec3(0.0, 0.0, 0.0);
  int level = 0;
  const int maxLevel = 5;
  
  // shot rays
  while(length(payload.nextRayDirection) > 0.1 &&
        level < maxLevel && length(contribution) > 0.001) {
    payload.level = level;
    // Submitting the camera ray to the acceleration structure traversal.
    // The last parameter is the index of the "payload" variable (always 0)
    traceRayEXT(topLevelAS, rayFlags, cullMask, 0u, 0u, 0u, 
            payload.nextRayOrigin, rayMin, payload.nextRayDirection, rayMax, 0);

    color += contribution * payload.radiance;
    contribution *= payload.nextFactor;
    level++;
  }

  if(frameID == 0) {
    gsnSetPixel(vec4(color, 1.0));
  } else {
    vec3 previousAverage = gsnGetPreviousPixel().rgb;
    previousAverage = pow(previousAverage, vec3(2.2)); // inverse gamma correction
    vec3 newAverage = (previousAverage.rgb * float(frameID) + color) / float(frameID + 1);
    newAverage = pow(newAverage, vec3(1.0 / 2.2)); // gamma correction
    gsnSetPixel(vec4(newAverage, 1.0));
  }
}

void  main() { /**** CLOSEST-HIT SHADER ****/
  
  // get mesh vertex data in object space
  vec3 p0, p1, p2;
  gsnGetPositions(gl_InstanceID, gl_PrimitiveID, p0, p1, p2);
  vec3 n0, n1, n2;
  gsnGetNormals(gl_InstanceID, gl_PrimitiveID, n0, n1, n2);
  vec2 t0, t1, t2;
  gsnGetTexCoords(gl_InstanceID, gl_PrimitiveID, t0, t1, t2);

  // interpolate with barycentric coordinate
  vec3 barys = vec3(1.0f - baryCoord.x - baryCoord.y, baryCoord.x, baryCoord.y);
  vec3 localNormal = normalize(n0 * barys.x + n1 * barys.y + n2 * barys.z);
  vec3 localPosition = p0 * barys.x + p1 * barys.y + p2 * barys.z;
  vec2 texCoords = t0 * barys.x + t1 * barys.y + t2 * barys.z;

  // transform to world space
  mat3 normalMat;
  gsnGetNormal3x3Matrix(gl_InstanceID, normalMat);
  vec3 normal = normalize(normalMat * localNormal);
  vec3 position = gl_ObjectToWorldEXT * vec4(localPosition, 1.0);

  // assign materials
  // Cornell Box
  vec3 baseColor = cornellWhite;
  vec3 emission = vec3(0.0);
  if(gl_InstanceID == 2 && texCoords.x < 0.25) {
    baseColor = cornellRed;
  } 
  if(gl_InstanceID == 2 && texCoords.x >= 0.5 && texCoords.x < 0.75) {
    baseColor = cornellGreen;
  }
  // light sphere
  if(gl_InstanceID == 1) {
    baseColor = vec3(0.0);
    emission = vec3(20.0);
  }
  
  // different random value for each pixel, each level, and each frame
  vec3 random = random_pcg3d(uvec3(gl_LaunchIDEXT.xy, frameID + payload.level));
  
  // uniform sampling of hemisphere
  float theta = 0.5 * PI * random.y;
  float phi = 2.0 * PI * random.x;
  
  payload.radiance = emission;
  
  // sampled indirect diffuse direction in normal space
  vec3 localDiffuseDir = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
  vec3 diffuseDir = getNormalSpace(normal) * localDiffuseDir;
  payload.nextRayOrigin = position;
  payload.nextRayDirection = diffuseDir;
  payload.nextFactor = baseColor * PI * cos(theta) * sin(theta);
}

void main() { /**** MISS SHADER ****/
  // set color to black
  payload.radiance = vec3(0.0, 0.0, 0.0);
  // no more reflections
  payload.nextRayOrigin = vec3(0.0, 0.0, 0.0);
  payload.nextRayDirection = vec3(0.0, 0.0, 0.0);
}

Importance Sampling

  • Die Riemann-Summe ist in der Regel keine sehr effiziente Lösung, da die Funktion gleichförmig abgetastet wird
  • Mit der so genannten "Importance Sampling" Theorie kann jedes Integral auch durch folgende Summe approximiert werden:
    $\int\limits_a^b \mathrm{f}(x) \,dx \approx \frac{1}{N} \sum\limits_{n=1}^{N} \frac{\mathrm{f}(x_n)}{\mathrm{p}(x_n)}$
    Dabei ist $\mathrm{p}(x)$ eine beliebige Wahrscheinlichkeitsdichtefunktion (WDF), die folgende Bedingung erfüllen muss
    $\int\limits_a^b \mathrm{p}(x) \, dx = 1$
  • Theoretisch wäre das beste WDF (mit dem geringsten Fehler der Approximation)
    $\mathrm{p}(x) = \frac{\mathrm{f}(x)}{ \int_a^b \mathrm{f}(x)}$
    was bedeutet, dass die WDF der Form der Funktion folgen sollte (d.h. die Dichte sollte höher sein, wenn die Funktionswerte höher sind).

Important Sampling

  • Übertragen auf die Rendering-Gleichung ergibt sich:
    $\begin{align}L_o(\mathbf{v}) &= L_e(\mathbf{v}) + \int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, L_i(\mathbf{l}) \cos(\theta) \, d\omega\\ &= L_e(\mathbf{v}) + \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi/2}\underbrace{ \mathrm{f}_r(\mathbf{v}, \mathbf{l})\,L_i(\mathbf{l}) \cos(\theta) \sin(\theta)}_{\mathrm{f}(\theta_n, \phi_n)} \, d\theta \, d\phi\\ &\approx L_e(\mathbf{v}) + \frac{1}{N} \sum_{n=1}^{N} \frac{\mathrm{f}(\theta_n, \phi_n)}{\mathrm{p}(\theta_n, \phi_n)} \end{align}$

Inversionsmethode

  • Die Wahrscheinlichkeitsdichtefunktion (WDF) $\mathrm{p}(x)$ kann beliebig gewählt werden
  • Um ein möglichst gutes Ergebnis nach wenig Abtastwerten zu bekommen, sollte die WDF der Form der Funktion folgen
  • Aber wie können Abtastpositionen mit einer bestimmten WDF generiert werden?
    • Viele Programmiersprachen stellen Funktionen bereit, um gleichverteilte Zufallszahlen zu erzeugen
    • Mit der Inversionsmethode ist es möglich, aus gleichverteilten Werten Zufallszahlen mit anderen WDF zu erzeugen
  • Inversionsmethode
    • Berechne die Verteilungsfunktion
      $\mathrm{P}_x(x) = \int\limits_{-\infty}^x p(\tilde{x}) \,d\tilde{x}$
    • Erzeuge gleichverteile Zufallswerte $u \in [0, 1]$
    • Berechne Zufallszahlen $x$ gemäß $\mathrm{p}(x)$ mit der Inversen der Verteilungsfunktion
      $x = \mathrm{P}^{-1}_x(u)$

Inversionsmethode: Beispiel 1 (diskrete Verteilung)

inversion_method
$p(x_n)$
$x_n$
$x_n$
$P_x(x)$
$u$
  • Acht Zufallsereignisse $x_n$ mit $n = 1,\dots,8$ mit gegebenem $p(x_n)$
  • Summe über alle $p(x_n)$ muss 1 sein
    $\sum\limits_{n=1}^8 p(x_n) = 1$
  • Die Verteilungsfunktion berechnet sich zu
    $P_x(x) = \sum\limits_{n=1}^x p(x_n)$
  • Inverse Verteilungsfunktion
    $x = \mathrm{P}^{-1}_x(u)$
  • Ist $u$ gleichverteilt, dann tritt Ereignis $x_n$ gemäß $p(x_n)$ auf

Inversionsmethode: Beispiel 2

inversion_example
$p(x)$
$x$
$P_x(x)$
$0$
$\pi$
$0$
$\pi$
$\frac{1}{2}$
  • Aufgabe:
    Erzeuge Zufallszahlen mit der WDF
    $p(x) = c \,\sin(x) \quad \quad x \in [0, \pi]$
  • Das Integral über die gesamte WDF muss 1 sein:
    $\int\limits_{0}^{\pi} c \sin(x) \,dx = \bigg[-\cos(x)\bigg]_{0}^{\pi} = 2 \,c = 1 \,\, \Rightarrow \,\, c = \frac{1}{2}$
  • Die Verteilungsfunktion berechnet sich zu
    $\mathrm{P}_x(x) = \int\limits_{0}^x \frac{1}{2} \sin(\tilde{x}) \,d\tilde{x} = \frac{1}{2} \bigg[-\cos(\tilde{x})\bigg]_{0}^{x} = \frac{1}{2} (1 - \cos(x)) $
  • Inverse Verteilungsfunktion
    $u = \frac{1}{2} (1 - \cos(x)) \Leftrightarrow x = \arccos(1 - 2\, u)$
  • Lösung:
    Ist $u$ gleichverteilt, hat $x = \arccos(1 - 2\, u)$ eine WDF von $p(x) = \frac{1}{2} \sin(x)$

Inversionsmethode bei einer 2D Wahrscheinlichkeitsdichte

  • Die Inversionsmethode kann auch bei einer zweidimensionalen WDF $p(x, y)$ angewendet werden
  • Dazu zunächst die Randdichte für eine Dimension berechnen, z.B. für $x$:
    $p(x) = \int p(x, y) \,dy$
  • Wird $x$ gemäß dieser WDF erzeugt, ergibt sich für die bedingte Wahrscheinlichkeit von $y$
    $p(y | x) = \frac{p(x, y)}{p(x)}$
  • Nun die bekannte Inversionsmethode jeweils für die zwei WDFs $p(x)$ und $p(y | x)$ anwenden
  • Alternativ können auch $p(y)$ und $p(x | y)$ verwendet werden

Abtastung einer Halbkugel

  • Nun zurück zum Important Sampling der Rendering-Gleichung:
    $\begin{align}L_o(\mathbf{v}) &= L_e(\mathbf{v}) + \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi/2}\underbrace{ \mathrm{f}_r(\mathbf{v}, \mathbf{l})\,L_i(\mathbf{l}) \cos(\theta) \sin(\theta)}_{\mathrm{f}(\theta_n, \phi_n)} \, d\theta \, d\phi\\ &\approx L_e(\mathbf{v}) + \frac{1}{N} \sum_{n=1}^{N} \frac{\mathrm{f}(\theta_n, \phi_n)}{\mathrm{p}(\theta_n, \phi_n)} \end{align}$
  • Die WDF $ \mathrm{p}(\theta, \phi)$ über der Halbkugel kann beliebig gewählt werden
  • Die Tabellen auf den nächsten Folien zeigen daher die Formeln zur Berechnung von Azimutwinkel $\phi$ und Polarwinkel $\theta$ eines Kugelkoordinatensystems aus zwei gleichverteilten Zufallsvariablen $u$ und $v$ im Bereich [0.0, 1.0] für die Abtastung einer Halbkugel mit verschiedenen WDFs
  • Die entsprechenden Herleitungen können hier gefunden werden:
    Importance Sampling einer Halbkugel
  • Interaktiver Demonstrator:
    Importance Sampling einer Halbkugel

Abtastung einer Halbkugel

WDF / AbbildungDraufsichtSeitenansicht
Gleichverteilt in Polarwinkeln
$\mathrm{p}(\theta, \phi) = \frac{1}{2\pi} \frac{1}{\pi/2}$
$\phi = 2 \pi \,u$
$\theta = \frac{\pi}{2}\, v$
(entspricht Riemann Summe)
uniform_theta_phi_top uniform_theta_phi_front
Gleichverteilt auf Halbkugel
$\mathrm{p}(\theta, \phi) = \frac{1}{2\pi} \,\sin(\theta)$
$\phi = 2 \pi \,u$
$\theta = \arccos(1 - v)$
uniform_hemi_top uniform_hemi_front

Abtastung einer Halbkugel

WDF / AbbildungDraufsichtSeitenansicht
Phong BRDF (Diffuser Anteil)
$\mathrm{p}(\theta, \phi) = \frac{1}{\pi} \, \cos(\theta) \,\sin(\theta)$
$\phi = 2 \pi \,u$
$\theta = \arcsin(\sqrt{v})$
cosine_hemi_top cosine_hemi_front
Phong BRDF (Spekularer Anteil)
$\mathrm{p}(\theta, \phi) = \frac{n_s + 1}{2 \pi} \, \cos(\theta)^{n_s} \,\sin(\theta)$
$\phi = 2 \pi \,u$
$\theta = \arccos\left((1-v)^{\frac{1}{n_s+1}}\right)$
phong_n40_top phong_n40_front

Abtastung einer Halbkugel

WDF / AbbildungDraufsichtSeitenansicht
Mikrofacetten GGX Verteilung mit
$r_p = 0.5$ und $\alpha = r_p^2$
$\mathrm{D}_{\tiny \mbox{GGX}}(\theta) = \frac{\alpha^2}{\pi \left(\cos^2(\theta) (\alpha^2-1)+1\right)^2}$
$\mathrm{p}(\theta, \phi) = \mathrm{D}_{\tiny \mbox{GGX}}(\theta)\cos(\theta)\sin(\theta)$
$\phi = 2 \pi \,u$
$\theta = \arccos\left(\sqrt{\frac{1 - v}{v (\alpha^2-1) + 1} }\right)$
ggx_050_top ggx_050_front
Mikrofacetten GGX Verteilung mit
$r_p = 0.25$
ggx_025_top ggx_025_front

Beispiel: Important Sampling bei diffuser BRDF

  • Diffuse BRDF:
    $\mathrm{f}_r(\mathbf{v}, \mathbf{l}) = \frac{\rho_d}{\pi}\quad$ mit $\quad\rho_d \in [0, 1]$
  • Gewählte WDF:
    $\mathrm{p}(\theta, \phi) = \frac{1}{\pi} \, \cos(\theta) \,\sin(\theta)$
  • Die Approximation des Integrals bei diffusen BRDF kann somit gelöst werden mit:
    $\begin{align}L_o(\mathbf{v}) &= L_e(\mathbf{v}) + \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi/2}\underbrace{ \mathrm{f}_r(\mathbf{v}, \mathbf{l})\,L_i(\mathbf{l}) \cos(\theta) \sin(\theta)}_{\mathrm{f}(\theta_n, \phi_n)} \, d\theta \, d\phi\\ &\approx L_e(\mathbf{v}) + \frac{1}{N} \sum_{n=1}^{N} \frac{\mathrm{f}(\theta_n, \phi_n)}{\mathrm{p}(\theta_n, \phi_n)}\\ &= L_e(\mathbf{v}) + \frac{\rho_d}{N} \sum_{n=1}^{N} L_i(\mathbf{l}(\theta_n, \phi_n)) \end{align}$
    mit $\phi_n = 2 \pi \,u$ und $\theta_n = \arcsin(\sqrt{v})$

Beispiel: Important Sampling bei diffuser BRDF

Beispiel: Important Sampling bei diffuser BRDF

  • Ohne Important Sampling (Riemann-Summe):
  • float theta = 0.5 * PI * random.y;
    float phi = 2.0 * PI * random.x;
    vec3 localDiffuseDir = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
    vec3 diffuseDir = getNormalSpace(normal) * localDiffuseDir;
    payload.nextRayOrigin = position;
    payload.nextRayDirection = diffuseDir;
    payload.nextFactor = baseColor * PI * cos(theta) * sin(theta);
  • Mit Important Sampling:
  • float theta = asin(sqrt(random.y));
    float phi = 2.0 * PI * random.x;
    vec3 localDiffuseDir = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
    vec3 diffuseDir = getNormalSpace(normal) * localDiffuseDir;
    payload.nextRayOrigin = position;
    payload.nextRayDirection = diffuseDir;
    payload.nextFactor = baseColor;  
    

Auswerten der Rendering-Gleichung

  • Das Beispiel zeigt, dass die Rendering Gleichung sehr einfach implementiert werden kann
  • Problem:
    • Bei der rekursiven Strahlverfolgung aus Sicht der Kamera gibt es nur einen Beitrag zur Strahldichte, wenn der Strahl zufälligerweise irgendwann die Lichtquelle trifft. Hat diese eine große Ausdehnung ist dies kein Problem, wird sie jedoch kleiner, wird die einfache Implementierung immer ineffizienter
    • Bei diffuser BRDF bringt das Important Sampling der BRDF nur leichte Verbesserungen
example_emissivesphere2
Jeweils 256 Samples pro Pixel

Auswerten der Rendering-Gleichung

  • Daher wird bei Path Tracing die Rendering Gleichung in zwei Anteile aufgeteilt
    • Direkter Anteil
    • Indirekter Anteil
  • Beim direkten Anteil wird der direkte Beitrag der Lichtquellen ausgewertet. Die Sichtbarkeit wird per Schattenstrahl überprüft. Bei ausgedehnten Lichtquellen muss die Position auf der Lichtquelle variiert werden.
  • Der indirekte Anteil wird, wie bisher, durch Weiterverfolgen einer zufällige Richtung im Halbraum ausgewertet. Allerdings dürfen die Lichtquellen natürlich nicht doppelt ausgewertet werden, so dass jetzt ein Treffer auf eine Lichtquelle keinen Beitrag zum indirekten Anteil liefert.
  • Die aufgeteilte Rendering-Gleichung:
    $L_o(\mathbf{v}) = \underbrace{\int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \, L_i(\mathbf{l}) \cos(\theta) \, d\omega}_{\small\mbox{direkter Anteil}} + \underbrace{\int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \, L_i(\mathbf{l}) \cos(\theta) \, d\omega}_{\small\mbox{indirekter Anteil}}$

Auswerten der Rendering-Gleichung

dwdA
$d\omega$
$dA$
$\theta_e$
$\theta$
$\mathbf{n}$
$\mathbf{n}_e$
$r_e$
Element der Lichtquelle
Element der Oberfläche
  • Beim direkten Anteil muss nun nicht mehr über den Halbraum integriert werden, sondern nur über den Raumwinkel aus dem direktes Licht auf die Oberfläche trifft
  • Dazu wird ein infinitesimales Flächenelement $dA$ der jeweiligen Lichtquelle umgerechnet in ein infinitesimales Raumwinkelelement $d\omega$
    $d\omega = \frac{cos(\theta_e)\, dA}{r_e^2}$
  • Das Integral des direkten Anteils kann dann über die Fläche der Lichtquelle ausgewertet werden
    $L_o(\mathbf{v}) = \underbrace{\int\limits_A \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \, L_i(\mathbf{l}) \, \frac{\cos(\theta) cos(\theta_e)\, }{r_e^2} V_e\,dA}_{\small\mbox{direkter Anteil}} + \underbrace{\int\limits_\Omega \mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \, L_i(\mathbf{l}) \cos(\theta) \, d\omega}_{\small\mbox{indirekter Anteil}}$
  • Die Sichtbarkeit $V_e$ des Flächenelements ist entweder 0 oder 1 und wird über den Schattenstrahl zur Lichtquelle bestimmt

Beispiel: Kugel als Flächenlicht

  • Betrachten wir das Beispiel einer Kugel mit Radius $r_s$ als Flächenlicht
  • Das Integral für den direkten Anteil kann per Importance Sampling gelöst werden:
    $\int\limits_A \underbrace{\mathrm{f}_r(\mathbf{v}, \mathbf{l})\, \, L_i(\mathbf{l}) \, \frac{\cos(\theta) cos(\theta_e)\, }{r_e^2} \,V_e}_{\mathrm{f}(x)}\,dA \approx \frac{1}{N} \sum\limits_{n=1}^{N} \frac{\mathrm{f}(x_n)}{\mathrm{p}(x_n)}$
  • Wenn die Kugel gleichmäßig abgetastet wird, müssen die Abtastpunkte auf der Kugeloberfläche wie folgt gewählt werden (siehe Inversionsmethode, Beispiel 2):
    $\theta_n = \arccos(1 - 2\,u)$ und $\phi_n = 2 \pi \,v$
  • Damit ist die WDF $\mathrm{p}(x)$ konstant und es muss weiterhin gelten:
    $\int_A \mathrm{p}(x) \, dx = 1$
    Da sich die gesamte Oberfläche einer Kugel mit Radius $r_s$ zu $4 \pi r_s^2$ berechnet, gilt:
    $\mathrm{p}(x) = \frac{1}{4 \pi r_s^2}$

Beispiel: Kugel als Flächenlicht

0.3 0.15 0.075 0.0375
compare_direct_indirect
Jeweils 256 Samples pro Pixel (oben ohne u. unten mit Abtasten des direkten Anteils)

Punktlichtquelle

pointlight
  • In alle Richtungen gleichmäßig sendend (isotrop)
  • Keine Ausdehnung (infinitesimal klein)
  • Vereinfachendes mathematisches Modell, nicht exakt physikalisch
  • Typische Parameter
    • 3D Position
    • Strahlungsfluss $\Phi$ in Watt $[\mathrm{W}]$

Punktlichtquelle

pointlight
$\mathbf{n}$
$-\mathbf{l}$
$-\mathbf{l}$
$\cos(\theta)dA$
$\theta$
$\theta$
$E_\perp$
$dA$
$dA$
  • Für ein Raumwinkelelement gilt
    $d\omega = \frac{cos(0) dA}{r^2} = \frac{dA}{r^2}$.
    Damit erzielt eine Punktlichtquelle bei
    Lichtstärke $I$ im Abstand $r$ eine senkrechte Bestrahlungsstärke von
    $E_\perp = \frac{d\Phi}{dA} = \frac{d\Phi}{d\omega \,r^2} = \frac{I}{r^2}$
  • Bei einem Einfallswinkel $\theta$ verringert sich die Fläche um $\cos(\theta)$. Damit gilt:
    $E = E_\perp \cos(\theta) = \frac{I}{r^2} \cos(\theta) = \frac{I}{r^2} \langle\mathbf{n} \cdot \mathbf{l}\rangle$

Punktlichtquelle

  • Da die Punktlichtquelle in alle Richtungen gleichmäßig sendet, besteht zwischen der Lichtstärke $I$ und dem Strahlungsfluss $\Phi$ die Beziehung:
    $\begin{align} &\Phi = \int\limits_{\Omega} I \, d\omega = \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi} I\, \sin(\theta) \, d\theta \, d\phi = I \Bigg[-\cos(\theta)\Bigg]_{0}^{\pi} \left(\int\limits_{0}^{2\pi}d\phi\right) = 4\pi \, I\\ \Leftrightarrow & I = \frac{\Phi}{4\pi} \end{align} $
  • Damit gilt für die Bestrahlungsstärke aus senkrechter Richtung im Abstand $r$:
    $E_\perp = \frac{I}{r^2} = \frac{\Phi}{4\pi \,r^2}$
  • bzw. bei Einfallswinkel $\theta$:
    $E = E_\perp \cos(\theta) = \frac{\Phi}{4\pi \,r^2} \cos(\theta) = \frac{\Phi}{4\pi \,r^2} \langle\mathbf{n} \cdot \mathbf{l}\rangle$

Beziehung Punktlichtquelle und Kugel als Flächenlicht

  • Ein Kugel mit Radius $r_s$ soll den gleichen Strahlungsfluss $\Phi$, wie eine Punktlichtquelle versenden. Wie groß muss die emittierte Strahldichte auf der Kugeloberfläche sein?
  • Strahldichte ist definiert als
    $L = \frac{d^2\Phi}{d\omega\, \cos(\theta) \,dA} = \frac{dI}{\cos(\theta) \,dA} \Leftrightarrow I = \int\limits_A L \cos(\theta) \,dA$
  • Die Sichtbarkeit der Fläche muss berücksichtigt werden, daher
    $\begin{align} I &= \int\limits_A L \cos(\theta) V(\theta) \,dA = \int\limits_\Omega L \cos(\theta) V(\theta) \, r_s^2 \,d\omega\\ &= \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi} L \cos(\theta) \sin(\theta) \, V(\theta) \, r_s^2 \, d\theta \, d\phi = L \,r_s^2 \int\limits_{0}^{2\pi}\, \int\limits_{0}^{\pi/2} \cos(\theta)\sin(\theta) \, d\theta \, d\phi = \\ &= L \,r_s^2\,\,2\pi \, \Bigg[\frac{-\cos^2(\theta)}{2}\Bigg]_{0}^{\pi/2} = L \,r_s^2\,\, \pi \Leftrightarrow L = \frac{I}{r_s^2\, \pi} = \frac{\Phi}{4 \pi \, \,r_s^2\, \pi} \end{align}$

Gibt es Fragen?

questions

Anregungen oder Verbesserungsvorschläge können auch gerne per E-mail an mich gesendet werden: Kontakt

Weitere Vorlesungsfolien

Folien auf Englisch (Slides in English)