<p>My path-tracer is generally fine and gives good output for regular test scenes, but I've noticed dense fireflies and dark speckles over fractal surfaces. The noise disappears if I render without light gathers (or zero every gather) and definitely isn't driven by hidden NaNs, so I suspect it's happening because fractals are naturally "rough" while my occlusion tests assume smooth surfaces (with constant shadow-ray offsets).</p>

<p>Would it be possible to evaluate local distance variance at each intersection and scale my shadow-ray offsets appropriately? Would it have a significant effect if so, or would I be better off writing a denoiser?</p>

<p>A few different test images with constant shadow offset; explicit light sampling is always performed with MIS (one BXDF sample, one spatial sample).</p>

<p><a href="https://i.sstatic.net/1h8gR.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/1h8gR.png" alt="Explicit light sampling, 4096spp, $2\epsilon$ ray offset"></a>
<em>Explicit light sampling for a fractal surface, 4096spp, $2\epsilon$ ray offset</em></p>

<p><a href="https://i.sstatic.net/A92E9.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/A92E9.png" alt="Classical path-tracing only, 4096spp, $2\epsilon$ ray offset"></a>
<em>Classical path tracing for a fractal surface, 4096spp, no explicit shadow rays</em></p>

<p><a href="https://i.sstatic.net/ubFUd.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/ubFUd.png" alt="Explicit light sampling for a sphere, 4096spp, $2\epsilon$ ray offset"></a>
<em>Explicit light sampling for a sphere, 4096spp, $2\epsilon$ ray offset</em></p>

<p><a href="https://i.sstatic.net/Yc4bn.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Yc4bn.png" alt="Classical path tracing for a sphere, 4096spp, $2\epsilon$ ray offset"></a>
<em>Classical path tracing for a sphere, 4096spp, no explicit shadow rays</em></p>

CC BY-SA 4.0
2018-07-25T08:50:16.977Z
Is it possible some intersections / shadow-ray-origins are landing inside your shape ? If your surfaces are 1 sided then from the inside you would almost certainly get a path to your large light, which would explain the bright pixels. I can see you have ring-artifacts on the sphere with explicit light sampling, which is usually a symptom of numerical imprecision. How is your shape defined? Is ray marching involved?
PaulHK
CC BY-SA 4.0
2018-07-25T10:40:22.317Z
Yes, everything's ray-marched directly inside the shader; the fractal is a quaternionic julia DE and the sphere is just the standard spherical SDF. I thought the same thing after I posted this, so I changed to an $8\epsilon$ offset instead. It fixed the ringing on the sphere, but didn't do anything for the noise on the julia's surface.
Paul Ferris
CC BY-SA 4.0
2018-07-27T02:02:55.547Z
Very thin sections of geometry can be a problem for ray marchers as you can step through them and if using a SDF you can get increased distance when the ray steps through a thin wall making this error hard to detect. Another issue is acute angle V shaped geometry were a ray could land in the part of the V where both faces are so close together that adding an epsilon from the surface of one side of the V means you end up behind the neighbouring surface.
PaulHK
CC BY-SA 4.0
2018-07-27T02:32:38.367Z
Mmm, that's why I wanted to adapt the offset to the local roughness. Tighter v-shapes should have smaller epsilons.
Paul Ferris
CC BY-SA 4.0
2018-07-27T02:35:09.517Z
I guess that doesn't stop shadow rays in rough areas being occluded after they leave, though. What would you suggest?
Paul Ferris
CC BY-SA 4.0
2018-07-27T05:39:53.150Z
That's a good question, I would try maybe a few small fixed ray march steps instead of adding an epsilon. If your shape is defined in such a way that you can test if a point is inside or outside you can consider the ray to be occluded if its epsilon adjusted start position is inside.
PaulHK
CC BY-SA 4.0
2018-07-27T08:25:06.000Z
So...you're suggesting I add an epsilon, intersection-test, add a smaller epsilon in the other direction if occluded, test again, and so on until the starting point is unoccluded? That's an interesting idea, thanks. I'll set things up and tell you how it goes :)
Paul Ferris
CC BY-SA 4.0
2018-07-27T08:26:56.820Z
RE: inside/outside checks - yes, I'm exclusively using signed distance fields. Every shape is positive on the outside and negative on the inside.
Paul Ferris
CC BY-SA 4.0
2018-07-31T03:52:49.400Z
Another interesting thing you could try for shadow rays is reverse ray-marching, marching from light to surface instead of the traditional path from surface->light. One headache with sphere raymarching is that its easier to walk into the field than it is to walk out of it, starting a ray near a surface results in small distances so you need several iterations to 'climb' out of it, you're only interested in the first occluder anyway so light->surface should result in less iterations over all.
PaulHK
CC BY-SA 4.0
2018-07-31T05:47:13.187Z
Wouldn't that present the same problem for points below the surface?
Paul Ferris
CC BY-SA 4.0
2018-07-31T06:05:48.860Z
It avoids making many small steps at the start. If we didn't have to worry about rounding then a ray from the surface would have a SDF distance of close to 0 so we would need to introduce epsilons/fixed steps to get things started, this step in itself can introduce artefacts. However walking it from the other direction doesn't have this problem as approaching from the outside means we start with large steps. Also since it will stop at the first occluder it should take less ray march steps globally.
PaulHK
CC BY-SA 4.0
2018-07-31T06:08:49.463Z
Also with WRT numerical imprecision, what happens if you start a ray slightly inside the surface, it will have a negative distance and a naive sphere marching would walk a ray in the wrong direction. At the very least you need abs(distance) on to ensure its always moving in the correct direction / away from surface.
PaulHK
CC BY-SA 4.0
2018-07-31T06:15:04.020Z
>.<. I can't believe I missed that, thanks.
What I meant was that subsurface points will be unreachable from the light source because light rays will hit the surface before they ever reach the point, and if you check within epsilon units of the point you re-introduce the precision errors from before.
Paul Ferris
CC BY-SA 4.0
2018-07-31T06:19:17.723Z
Yeah, I don't think you could ever fully fix SDF artefacts. Glancing rays are another issue (say a ray which is close and parallel to a surface would need a huge number of steps to escape and most ray marchers would hit some pre-defined max-steps limit and assume its either solid or empty, yet change the angle slightly so it 'climbs' out then you suddenly get different results. In a path tracer this would manifest as a source of random noise.
PaulHK
CC BY-SA 4.0
2018-07-31T08:07:33.167Z
eh, your help from before pushed things down a lot, and I wrote a small denoiser to minimize leftover speckling/fireflies :); here's a current sphere @ 4096spp (https://imgur.com/a/AynFlY2) and here's a current Julia (https://imgur.com/a/7Cu66gr) (same sample count).
Paul Ferris
CC BY-SA 4.0
2018-07-31T08:10:46.593Z
RE: glancing rays - yeah, that's definitely another noise source. I don't really mind having some grain though, and I feel like ringing looks ok so long as it's subtle enough. Avoiding harsh black-on-white or white-on-black pixels is good enough for me :).
Paul Ferris
<pathtracing><shadow><importance-sampling>
Handling shadow acne for dynamic surfaces
Paul Ferris
# Handling shadow acne for dynamic surfaces

(Asked by: username_0 on 2018-07-25)

My path-tracer is generally fine and gives good output for regular test scenes, but I've noticed dense fireflies and dark speckles over fractal surfaces. The noise disappears if I render without light gathers (or zero every gather) and definitely isn't driven by hidden NaNs, so I suspect it's happening because fractals are naturally "rough" while my occlusion tests assume smooth surfaces (with constant shadow-ray offsets).

Would it be possible to evaluate local distance variance at each intersection and scale my shadow-ray offsets appropriately? Would it have a significant effect if so, or would I be better off writing a denoiser?

A few different test images with constant shadow offset; explicit light sampling is always performed with MIS (one BXDF sample, one spatial sample).

[![Explicit light sampling, 4096spp, $2\epsilon$ ray offset](https://i.sstatic.net/1h8gR.png)](https://i.sstatic.net/1h8gR.png)
*Explicit light sampling for a fractal surface, 4096spp, $2\epsilon$ ray offset*

[![Classical path-tracing only, 4096spp, $2\epsilon$ ray offset](https://i.sstatic.net/A92E9.png)](https://i.sstatic.net/A92E9.png)
*Classical path tracing for a fractal surface, 4096spp, no explicit shadow rays*

[![Explicit light sampling for a sphere, 4096spp, $2\epsilon$ ray offset](https://i.sstatic.net/ubFUd.png)](https://i.sstatic.net/ubFUd.png)
*Explicit light sampling for a sphere, 4096spp, $2\epsilon$ ray offset*

[![Classical path tracing for a sphere, 4096spp, $2\epsilon$ ray offset](https://i.sstatic.net/Yc4bn.png)](https://i.sstatic.net/Yc4bn.png)
*Classical path tracing for a sphere, 4096spp, no explicit shadow rays*

**Tags:** pathtracing, shadow, importance-sampling

> **Comments:**
> **username_1**: Is it possible some intersections / shadow-ray-origins are landing inside your shape ? If your surfaces are 1 sided then from the inside you would almost certainly get a path to your large light, which would explain the bright pixels. I can see you have ring-artifacts on the sphere with explicit light sampling, which is usually a symptom of numerical imprecision. How is your shape defined? Is ray marching involved?  
> **username_0**: Yes, everything's ray-marched directly inside the shader; the fractal is a quaternionic julia DE and the sphere is just the standard spherical SDF. I thought the same thing after I posted this, so I changed to an $8\epsilon$ offset instead. It fixed the ringing on the sphere, but didn't do anything for the noise on the julia's surface.  
> **username_1**: Very thin sections of geometry can be a problem for ray marchers as you can step through them and if using a SDF you can get increased distance when the ray steps through a thin wall making this error hard to detect. Another issue is acute angle V shaped geometry were a ray could land in the part of the V where both faces are so close together that adding an epsilon from the surface of one side of the V means you end up behind the neighbouring surface.  
> **username_0**: Mmm, that's why I wanted to adapt the offset to the local roughness. Tighter v-shapes should have smaller epsilons.  
> **username_0**: I guess that doesn't stop shadow rays in rough areas being occluded after they leave, though. What would you suggest?  
> **username_1**: That's a good question, I would try maybe a few small fixed ray march steps instead of adding an epsilon. If your shape is defined in such a way that you can test if a point is inside or outside you can consider the ray to be occluded if its epsilon adjusted start position is inside.  
> **username_0**: So...you're suggesting I add an epsilon, intersection-test, add a smaller epsilon in the other direction if occluded, test again, and so on until the starting point is unoccluded? That's an interesting idea, thanks. I'll set things up and tell you how it goes :)  
> **username_0**: RE: inside/outside checks - yes, I'm exclusively using signed distance fields. Every shape is positive on the outside and negative on the inside.  
> **username_1**: Another interesting thing you could try for shadow rays is reverse ray-marching, marching from light to surface instead of the traditional path from surface->light. One headache with sphere raymarching is that its easier to walk into the field than it is to walk out of it, starting a ray near a surface results in small distances so you need several iterations to 'climb' out of it, you're only interested in the first occluder anyway so light->surface should result in less iterations over all.  
> **username_0**: Wouldn't that present the same problem for points below the surface?  
> **username_1**: It avoids making many small steps at the start. If we didn't have to worry about rounding then a ray from the surface would have a SDF distance of close to 0 so we would need to introduce epsilons/fixed steps to get things started, this step in itself can introduce artefacts. However walking it from the other direction doesn't have this problem as approaching from the outside means we start with large steps. Also since it will stop at the first occluder it should take less ray march steps globally.  
> **username_1**: Also with WRT numerical imprecision, what happens if you start a ray slightly inside the surface, it will have a negative distance and a naive sphere marching would walk a ray in the wrong direction. At the very least you need abs(distance) on to ensure its always moving in the correct direction / away from surface.  
> **username_0**: >.<. I can't believe I missed that, thanks. What I meant was that subsurface points will be unreachable from the light source because light rays will hit the surface before they ever reach the point, and if you check within epsilon units of the point you re-introduce the precision errors from before.  
> **username_1**: Yeah, I don't think you could ever fully fix SDF artefacts. Glancing rays are another issue (say a ray which is close and parallel to a surface would need a huge number of steps to escape and most ray marchers would hit some pre-defined max-steps limit and assume its either solid or empty, yet change the angle slightly so it 'climbs' out then you suddenly get different results. In a path tracer this would manifest as a source of random noise.  
> **username_0**: eh, your help from before pushed things down a lot, and I wrote a small denoiser to minimize leftover speckling/fireflies :); here's a current sphere @ 4096spp (https://imgur.com/a/AynFlY2) and here's a current Julia (https://imgur.com/a/7Cu66gr) (same sample count).  
> **username_0**: RE: glancing rays - yeah, that's definitely another noise source. I don't really mind having some grain though, and I feel like ringing looks ok so long as it's subtle enough. Avoiding harsh black-on-white or white-on-black pixels is good enough for me :).  

---

## 0 answers

