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 zooming: enter image description here more: enter image description here increasing the distance and the radius of the orange sphere: enter image description here


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;
    h.t = length;
    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);
    mult_(color, diff, color);
    add_(ambi, color, color);

  • 1
    $\begingroup$ I suspect you have "surface/shadow acne". Typically you may need to add an "epsilon" offset to the starting position of secondary rays. $\endgroup$
    – Simon F
    Jul 1, 2021 at 8:22
  • 1
    $\begingroup$ 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. $\endgroup$
    – LesChats
    Jul 1, 2021 at 16:09
  • 1
    $\begingroup$ 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) $\endgroup$
    – pmw1234
    Jul 2, 2021 at 10:50
  • $\begingroup$ 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 $\endgroup$
    – LesChats
    Jul 6, 2021 at 11:25


Your Answer

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

Browse other questions tagged or ask your own question.