<p><strong>situation:</strong></p>
<p>I've implemented a Whitted style ray tracing in C. Everything appear to works except the shadow cast by small object on big far objects</p>
<p><strong>The problem :</strong></p>
<p>red sphere have radius 0.5
orange sphere have radius 200
<a href="https://i.sstatic.net/siIfu.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/siIfu.png" alt="example" /></a>
zooming:
<a href="https://i.sstatic.net/2BAk1.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/2BAk1.png" alt="enter image description here" /></a>
more:
<a href="https://i.sstatic.net/uaVmE.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/uaVmE.png" alt="enter image description here" /></a>
increasing the distance and the radius of the orange sphere:
<a href="https://i.sstatic.net/rzCnQ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/rzCnQ.png" alt="enter image description here" /></a></p>
<p><strong>Question:</strong></p>
<p>So fare, I could only suspect rounding error due to the fact that I use float.
In &quot;normal&quot; situation, the shadows work great.
Have you already encounter that kind of error ? Is my guess correct, or could that be something else ?</p>
<p>Not sure the code could help because messy, but there it is:</p>
<pre><code>static inline uint8_t   diffuse(const struct s_bvh *bvh,
    const t_lght *lght, const t_hinfo *hi, t_vec3f diff)
{
    t_vec3f         light;
    struct s_hit    h;
    float           dp;
    float           length;
    
    //make the [hit_pts -&gt; light_pts] vector
    sub_(lght-&gt;pts, hi-&gt;r-&gt;o, hi-&gt;r-&gt;d);
    length = norm(hi-&gt;r-&gt;d);
    //minimum to avoid self intersection
    h.min = 0.001f;
    //maximum 
    h.t = length;
    normalize(hi-&gt;r-&gt;d);
    dp = dotp(hi-&gt;n, hi-&gt;r-&gt;d);
    if (dp &gt; 0.0f)
    {
        //invertion fo the ray_direction and traverse the BVH tree
        invert_(hi-&gt;r-&gt;d, hi-&gt;r-&gt;inv_d);
        traverser(bvh, hi-&gt;r, &amp;h, 1);
        //if in shadow, return (0)
        if (h.t &lt; length)
            return (0);
        // else apply the light
        s_scale(lght-&gt;color, dp, light);
        add_(light, diff, diff);
        return (1);
    }
    return (0);
}

void    diffusel(const struct s_bvhl *s, const t_hinfo *hi, t_vec3f color)
{
    t_vec3f         ambi;
    t_vec3f         diff;
    uint32_t        i;

    i = 0;
    mult_(s-&gt;lghts.amb, color, ambi);
    set_vector(diff, 0.f, 0.f, 0.f);
    //for each light
    while (i &lt; s-&gt;lghts.count)
    {
        diffuse(&amp;s-&gt;bvh, s-&gt;lghts.lghts + i, hi, diff);
        ++i;
    }
    mult_(color, diff, color);
    add_(ambi, color, color);
}

</code></pre>

CC BY-SA 4.0
2021-07-01T08:22:17.600Z
I suspect you have "surface/shadow acne".  Typically you may need to add an "epsilon" offset to the starting position of secondary rays.
Simon F
CC BY-SA 4.0
2021-07-01T16:09:14.190Z
Thank you for your reply Simon F,  I think that if it was shadow acne the bug/artifact will be spread on all the shadow surface. For prevent self intersection my implementation use a min value (epsilon) so that any intersection find under that min is discarded. Anyway, I add an epsilon vector to the start of the shadow ray, as you propose. Unfortunately nothing change.
Many thanks for your time, I really think now that the "bug" is the result of rounding error, so there is nothing I can do about it with my current knowledge.
LesChats
CC BY-SA 4.0
2021-07-02T10:50:22.937Z
Floating point rounding error at the size and distance you are talking about is less then 0.0001. I checked. If that much quantization is building to cause a visible error, then there is a bug in the code that is amplifying it, either way this is a coding bug. (reposted original copy pasted wrong value)
pmw1234
CC BY-SA 4.0
2021-07-06T11:25:10.347Z
Interesting answer pmw1234
The problem scale with the distance / radius difference between the two objects.
Need to precise that I use a BVH tree and for that I invert the ray direction in the intent to speed up the search (inv_d = {1/r.x, 1/r.y, 1/r.z}). I was thinking that the main source of error could come from floating error in that process. 

Anyway I will review my code hoping that the flaw come, as you stated, from it.
Thank you for your concern <3
LesChats
<raytracing><shadow><artifacts><debugging>
ray racing (Whitted) bad shadow on far objects (artifact)
LesChats
# ray racing (Whitted) bad shadow on far objects (artifact)

(Asked by: username_0 on 2021-06-30)

**situation:**

I've implemented a Whitted style ray tracing in C. Everything appear to works except the shadow cast by small object on big far objects

**The problem :**

red sphere have radius 0.5
orange sphere have radius 200
[![example](https://i.sstatic.net/siIfu.png)](https://i.sstatic.net/siIfu.png)
zooming:
[![enter image description here](https://i.sstatic.net/2BAk1.png)](https://i.sstatic.net/2BAk1.png)
more:
[![enter image description here](https://i.sstatic.net/uaVmE.png)](https://i.sstatic.net/uaVmE.png)
increasing the distance and the radius of the orange sphere:
[![enter image description here](https://i.sstatic.net/rzCnQ.png)](https://i.sstatic.net/rzCnQ.png)

**Question:**

So fare, I could only suspect rounding error due to the fact that I use float.
In "normal" situation, the shadows work great.
Have you already encounter that kind of error ? Is my guess correct, or could that be something else ?

Not sure the code could help because messy, but there it is:

```
static inline uint8_t   diffuse(const struct s_bvh *bvh,
    const t_lght *lght, const t_hinfo *hi, t_vec3f diff)
{
    t_vec3f         light;
    struct s_hit    h;
    float           dp;
    float           length;
    
    //make the [hit_pts -> light_pts] vector
    sub_(lght->pts, hi->r->o, hi->r->d);
    length = norm(hi->r->d);
    //minimum to avoid self intersection
    h.min = 0.001f;
    //maximum 
    h.t = length;
    normalize(hi->r->d);
    dp = dotp(hi->n, hi->r->d);
    if (dp > 0.0f)
    {
        //invertion fo the ray_direction and traverse the BVH tree
        invert_(hi->r->d, hi->r->inv_d);
        traverser(bvh, hi->r, &h, 1);
        //if in shadow, return (0)
        if (h.t < length)
            return (0);
        // else apply the light
        s_scale(lght->color, dp, light);
        add_(light, diff, diff);
        return (1);
    }
    return (0);
}

void    diffusel(const struct s_bvhl *s, const t_hinfo *hi, t_vec3f color)
{
    t_vec3f         ambi;
    t_vec3f         diff;
    uint32_t        i;

    i = 0;
    mult_(s->lghts.amb, color, ambi);
    set_vector(diff, 0.f, 0.f, 0.f);
    //for each light
    while (i < s->lghts.count)
    {
        diffuse(&s->bvh, s->lghts.lghts + i, hi, diff);
        ++i;
    }
    mult_(color, diff, color);
    add_(ambi, color, color);
}

```

**Tags:** raytracing, shadow, artifacts, debugging

> **Comments:**
> **username_1**: I suspect you have "surface/shadow acne".  Typically you may need to add an "epsilon" offset to the starting position of secondary rays.  
> **username_0**: Thank you for your reply username_1 F,  I think that if it was shadow acne the bug/artifact will be spread on all the shadow surface. For prevent self intersection my implementation use a min value (epsilon) so that any intersection find under that min is discarded. Anyway, I add an epsilon vector to the start of the shadow ray, as you propose. Unfortunately nothing change. Many thanks for your time, I really think now that the "bug" is the result of rounding error, so there is nothing I can do about it with my current knowledge.  
> **username_2**: Floating point rounding error at the size and distance you are talking about is less then 0.0001. I checked. If that much quantization is building to cause a visible error, then there is a bug in the code that is amplifying it, either way this is a coding bug. (reposted original copy pasted wrong value)  
> **username_0**: Interesting answer username_2 The problem scale with the distance / radius difference between the two objects. Need to precise that I use a BVH tree and for that I invert the ray direction in the intent to speed up the search (inv_d = {1/r.x, 1/r.y, 1/r.z}). I was thinking that the main source of error could come from floating error in that process.   Anyway I will review my code hoping that the flaw come, as you stated, from it. Thank you for your concern <3  

---

## 0 answers

