Home » Programming » C++ Raytracer » Ray Tracer Part One – What is Raytracing?

Ray Tracer Part One – What is Raytracing?

gridcoin728x90_40b-99980e

The following image was generated by a raytracer I have written in C++.  I originally wrote this as a programming assignment for a course at Canterbury University, COSC363 – Computer Graphics.  The program can be downloaded from this page.

RT1

This render illustrates many of the features currently implemented.  Supported object types are spheres, cones, boxes, and surfaces, these objects can be made reflective or refractive, and have textures applied to add realism. Area light sources allow soft shadows to be cast.  Surfaces can be bump mapped, giving the impression of an irregular surface (or water surface with refraction) , or even used to create a complex 3D surface.  A depth of field camera can also be used, to bring objects at a certain distance into focus, while leaving others blurry.  An environment map can be used to surround the scene, and fill in that dead space, and makes reflections look much more realistic. A KD-tree is used to speed up the raytracing process when a large number of objects is added.  Photon Mapping is also supported, allowing caustic lighting with refractive objects.

The basic idea

Raytracing Concept

Raytracing generates an image by tracing the path of light from an eye point, through each pixel of an image, and coloring each pixel depending on the objects the ray intercepts in it’s path.  When a ray hits an object, the color contribution of that hit is calculated (depending on material properties, and lighting…) and if the material is reflective or refractive, additional rays are calculated and traced until a certain end condition is met.  When a ray hits a reflective object a reflective ray is generated.  When a ray hits a transparent object two rays must be generated; a reflective ray and a transmission ray.

The basic raytracing algorithm

Probably the easiest way to implement  a raytracer is by using recursion.  The following pseudocode is not supposed to be in anyway complete or concise, but is rather intended to provide a simple introduction to the idea.

Render(){
   for each pixel in image {
      viewRayOrigin = eyePoint;
      viewRay       = currentPixelLocation - eyePoint;
      maxRecursiveDepth = 7; // or more
      traceRay(viewRayOrigin, viewRay, currentPixelColor, maxRecursiveDepth)
   }
}

traceRay(origin, viewRay, pixelColor, depth){
  if(depth <= 0) // our end condition
     return;

  nearestObject = getNearestIntersection(origin, viewRay, interceptDistance);   

  interceptPoint = origin + viewRay*interceptDistance;
  pixelColor += calculateLighting(nearestObject, interceptPoint);

  if(nearestObject is transparent){
     transmissionRay = getTransmissionRay(....);
     traceRay(interceptPoint, transmissionRay, pixelColor, depth-1);
  }

  if(nearestObject is reflective or is transparent){
    reflectiveRay = getReflectiveRay(...);
    traceRay(interceptPoint, reflectiveRay, pixelColor,depth-1);
  }
}

Now obviously many details have been left out from this, and as you develop your code you will undoubtedly encounter undesired visual artifacts at some point.

If you are new to computer graphics or ray tracing, some of these terms may be new to you, but it is my intention to introduce these topics in an easy to digest manner, and provide an explanation of how these features can be implemeted so hopefully you too can create a working ray tracer.  Ray tracing is very computationally expensive, so consider this when deciding which language to use.

Next – Creating the Camera


Leave a comment

Contact

Email: sjh148@uclive.ac.nz