2
$\begingroup$

I am working my way through my first path tracer and I am currently designing how to deal with area lights. I have two questions:

Each object in my scene can have a Light attached to it, this is how I represent Area Lights. Given this I have two questions:

1) Shadow ray: When doing shadows, if I use a blind IsOccluded function that I use successfully for point lights, I will obviously have always an "occluded" result, as the light vector by construction ends up at the light source itself which is an object in my scene and therefore will be hit by the shadow ray.

To rephrase, how do I deal nicely with the light being an object in my scene when casting the shadow ray for that light?

I would like to keep my IsOccluded function simple, returning only a boolean and not a position/interaction record. At first glance PBRT manages to do so, but I don't understand how they get around the problem. Am I forced to use a different scene intersection function? If so, what is the most graceful way to solve the problem?

2) Secondary rays: If I have more than one bounce, I often see this black dots appearing (even if I disable shadows). I know this is hard without more context, but I wonder if someone has encountered something like this or can guess:

With multiple bounces

enter image description here

With only first hit

enter image description here

I thought it could be related to the way I sample the sphere, but if that was the case, shouldn't I get black dots even with only one event? I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated. I am guessing I am trying to lit the light with the light itself, causing a NaN that gets then propagated. Does it make sense? I am more interested to understand the cause than how to fix this.

3) Bright pixels: Somewhat unrelated? (I can open separate question), but I get lots of unnaturally bright pixels all over the place if I have more than 2 bounces. What is the cause of this? How do I fix this?

Also, do you have any suggestion on how to handle area light sources that I am clearly missing here?

Thank you and sorry for the probably confused question, I am happy to edit it if you have suggestions.

$\endgroup$
1
  • 2
    $\begingroup$ "I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated." The common scenario is that you're using floating-point and you have a bug in your code :-) You have to expect that you'll get NaNs during development, so you should either (a) make sure they get filtered out instead of propagated by the filter, or (b) show all NaNs as bright pink so it's immediately obvious when they're there. $\endgroup$
    – Dan Hulme
    Commented Sep 25, 2017 at 15:26

1 Answer 1

3
$\begingroup$

I am no expert in offline renderers, but I'll give it a go until someone else comes with a better answer :)

Shadow rays intersecting area light

It is very common to assign an extent to your rays. How to do so? Think about the parametric formula of a ray:

$$R(t) = O + t\vec{D}$$

it should immediately jumps out that how far $R(t)$ can be from the origin $O$ depends on how much we can travel in the direction $\vec{D}$, and this travelling is clearly governed by the parameter $t$.

Your problem here is that you don't want to let the ray travel indefinitely, but you want to stop just before it hits the source of the light, because otherwise, as you correctly noticed, everything will result occluded.

So how do you limit how much your ray can travel? You just have to limit the maximum value that $t$ can take. You have two option:

  1. Probably the most intuitive one is to compute at what $t_{light}$ your light source lies. By using the same parametric formulation of the ray, if $L_p$ is the point you've chosen on the area light, then $t_{light}$ will be:

$$t_{light} = \frac{L_{p}[i] - O[i]}{\vec{D}[i]}$$ where $[i]$ represents the coordinate of your choice. Given this, you want to stop your shadow ray to travel just before $t$ reaches $t_{light}$. If it goes over this value, report an unoccluded result.

  1. Now while the option above is probably the first thing that comes to mind, it is wasteful as you'd need to both have $L_p$ around and perform some unneeded arithmetic operations if you have your light vector $\vec{D}$ as unnormalized around. In fact, this is none other than $L_p - O$ and in a case like this, the Light lies at exactly $t == 1$:

$$ O + 1 \times (L_p - O ) = L_p $$

So if you trace your shadow ray with an unnormalized direction $\vec{D}$, you can just set your maximum $t$ to be just under $1$. This is in fact what PBRT does, and as far as I am aware many other renderers.

Black dots (or NaNs)

Nothing to add over @Dan Hulme comment, so I'll just add it here for completeness of the answer:

"I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated." The common scenario is that you're using floating-point and you have a bug in your code :-) You have to expect that you'll get NaNs during development, so you should either (a) make sure they get filtered out instead of propagated by the filter, or (b) show all NaNs as bright pink so it's immediately obvious when they're there. – Dan Hulme♦

and if I may add, you should expect some inf as well from time to time, so it's always good to account for these two special cases.

"Bright pixels"

With that, I assume you are talking about what is commonly referred to as fireflies. Fireflies avoidance is indeed quite a big topic and probably warrant its own question. However, just briefly.

Fireflies typically occur when you lots of your paths end in areas with low light and very few paths end up in very bright light. There is lots of material on how to fight fireflies, a short google search will lead to a lot of techniques depending on your case. Just to name drop a few:

  • Radiance clamping
  • Multiple Importance Sampling (especially if in presence of glossy/shiny surfaces)
  • Denoising techniques
  • Increment your sample count :-)
  • etc.

Also, generally increasing the size of the light source tends to help as well. Remember, the goal is always to hit those bright spot with higher probability!

A better solution to the problem is probably to use something like Bidirectional Path Tracing as this will have sub-paths starting from the light source as well, increasing the likelihood of sampling the bright areas.

Another cause of fireflies are caustics, but I don't want to make this answer longer, so if you are interested this is well worth an additional question.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.