Search code examples
c++recursionglsltail-recursionraytracing

Getting diffuse material right form cpu code to gpu shader


I'm trying to unwarp this function from raytracing in one weekend

vec3 color(const ray& r, hitable *world)
{
   hit_record rec;
   if(world->hit(r,0.0, MAXFLOAT, rec)){
      vec3 target = rec.p + rec.normal + random_in_unit_sphere();
      return 0.5*color( ray(rec.p, target-rec.p), world);
   }
   else{
      vec3 unit_direction = unit_vector(r.direction());
      float t = 0.5*(unit_direction.y() + 1.0);
      return (1.0-t)*vec3(1.0,1.0,1.0) + t*vec3(0.5,0.7,1.0);
   }
}

i've understand that it will send a ray and bounce it until it does not hit anything.
So i have attempt to unwarp this recursive function in a GLSL shader.

vec3 color(ray r, hitableList list)
{
    hitRecord rec;
    vec3 unitDirection;
    float t;
    while(hit(r, 0.0, FLT_MAX, rec, list))
    {
        vec3 target = rec.p + rec.normal;
        r = ray(rec.p, target-rec.p);
    }
    unitDirection = normalize(direction(r));
    t = 0.5* (unitDirection.y + 1.);
    return (1.-t)*vec3(1.)+t*vec3(0.5,0.7,1.);
}

normally it should output a diffuse like this :
Actual diffuse material on cpu

but i only get a reflective material like this :
Attempt one of the GPU diffuse material

note, the material is HIGHLY reflective and can reflect other sphere in the scene.
i have looked around the code and something tell me it's my wrong approche of this tail recursive fonction.
Also I don't return the 0.5 * the return 0.5 * color(...) I have no idea how to do it.

UPDATE

Thanks to the awnser of Jarod42 there is now the 0.5 * factor implemented, this solve the issue of the material not being "properly" expose to light.
But now the diffuse material is still not generated, I end up with a Metal Material fully reflective.
Attempt two of the diffuse material


Solution

  • To use the factor of 0.5, you might do something like:

    vec3 color(ray r, hitableList list)
    {
        hitRecord rec;
        vec3 unitDirection;
        float t;
        float factor = 1.f;
    
        while(hit(r, 0.0, FLT_MAX, rec, list))
        {
            vec3 target = rec.p + rec.normal;
            r = ray(rec.p, target-rec.p);
            factor *= 0.5f;
        }
        unitDirection = normalize(direction(r));
        t = 0.5* (unitDirection.y + 1.);
        return factor * ((1.-t)*vec3(1.)+t*vec3(0.5,0.7,1.));
    }