Search code examples
c++graphics3draytracing

Getting absurd reflections on a sphere in Raytracing


I am trying to implement a simple CPU based Raytracer in C++. But on implementing the Reflections in the scene I am getting some absurd results, the reflections are not covering the whole object that I am trying to get reflections on. I have attached the image for reference.

Here is the Reflection Algorithm I am using.

//reflected ray
                  Vec3 ref =(dir - 2*((dir.dot(Normal))*Normal)).normalized();
                  Vec3 reflect_orig;

                  if(depth < MAX_DEPTH && figurelist[figureHit]->reflectness>0.0f ){
                      if(ref.dot(Normal)<0.0f){

                          reflect_orig = p0 - (Normal*0.001f);

                      }
                      else{
                          reflect_orig = p0 + (Normal*1e-3f);
                      }
                      reflectcolour = reflectcolour+ray_trace(reflect_orig,ref,depth+1);
                      return Pixelcolour = reflectcolour;
                  }
                  else{
                     Pixelcolour = diffuse+specular;
                  }

where "dir" is the direction of ray.

The output image


Solution

  • the image does not looks so bad. When I tried to recreate your scene in mine GLSL ray tracer I got this result:

    result

    As you can see it is not that much different apart of the different lighting. I only guessed the positions, sizes, colors, reflection and refraction coefficients so my scene is not exact the same as yours:

    ray.beg();
    //                 r   g   b rfl rfr   n                               x     y     z   rx   ry   rz
    ray.add_material(0.8,0.8,0.6,0.0,0.0,_n_glass); ray.add_box       (  0.0,  0.0,-10.0,10.0,10.0, 0.1);
    ray.add_material(0.8,0.8,0.6,0.0,0.0,_n_glass); ray.add_box       (  0.0,  0.0,+10.0,10.0,10.0, 0.1);
    ray.add_material(1.0,0.1,0.1,0.0,0.0,_n_glass); ray.add_box       (-10.0,  0.0,  0.0, 0.1,10.0,10.0);
    ray.add_material(0.1,1.0,0.1,0.0,0.0,_n_glass); ray.add_box       (+10.0,  0.0,  0.0, 0.1,10.0,10.0);
    ray.add_material(0.8,0.6,0.8,0.0,0.0,_n_glass); ray.add_box       (  0.0,-10.0,  0.0,10.0, 0.1,10.0);
    ray.add_material(0.8,0.6,0.8,0.0,0.0,_n_glass); ray.add_box       (  0.0,+10.0,  0.0,10.0, 0.1,10.0);
    //                 r   g   b rfl rfr   n                               x     y     z   r
    ray.add_material(0.7,0.0,0.0,0.0,0.0,_n_glass); ray.add_sphere    (+ 1.5,- 1.5,+ 0.5,1.5);
    ray.add_material(0.0,0.0,0.7,0.8,0.0,_n_glass); ray.add_sphere    (- 1.5,+ 1.5,- 0.5,1.5);
    ray.end();
    

    I use these indexes:

    const GLfloat _n_glass=1.561;
    const GLfloat _n_vacuum=1.0;
    

    The distortion (no reflection present) on edges of your blue sphere might be caused by low precision did you used doubles ? I do not know what libs you are using but Vec3 usually means only floats try dVec3 or what ever ... the problem might be related to this:

    Which on pure floats tend to cause similar artifacts even noise on edges of reflective/refractive spheres. Here the same engine of mine but on floats:

    float noise

    as you can see the noise is more often in areas where your output does not reflect at all which indicates similar cause...

    However I see in your image some aspect ratio distortions like you expect square window and got 640x480 rectangle instead so you got no or inverse aspect ratio correction. This can slightly mess the casted rays directions and further distort image after reflect/refract ...