C++ Implementation of RayTracing Algorithm

The Algorithm

The Code

The Shots

The Source - raytracing.tar.gz

Back to Ronald's Site


The Algorithm

I'm not bothering in to explain Raytracing, you can read Wikipedia for that. Anyway its basically a recursive algorithm to calculate the quantity of light that is reflected from a raylight in to the direction of an observer outside the screen.

So to do this we basically have to follow this steps:

  1. Trace a ray from the observer and find the collision point for the fist object on the screen.
  2. At that point you can calculate if it is illuminated by a light source or maybe if it is blocking the light from a source, that is made with wath we call Shadowfeelers (name as deltas in my code).

The Code

Here I post the code that do the main algorithm. What it does is to go pixel by pixel and execute the recursive RayTrace function to calculate the final light intensity and at the end the color of that pixel.

void RayTracing(){
        vector  color;
        vector u;
        vector x;
        double X,Y,Z;
        x.x=X0; x.y=Y0; x.z=Z0;
        background.x=0;background.y=0;background.z=0;
        for(int i=0;i<Width;i++){
                for (int j=0; j < Height; j++) {
                        gluUnProject(i,j,0.5,mvmatrix,projmatrix,viewport,
                                &X,&Y,&Z); // pixel al principio
                        vector point3d = vector((float)X,(float)Y,(float)Z);
                        u = point3d-x;
                        u.Normalize();
                        color = RayTrace(x,u,MAXDEPTH, objects,background,ampolleta);
                        glColor3f(color.x,color.y,color.z);
                        glBegin(GL_POINTS);
                                glVertex3f(point3d.x,point3d.y,point3d.z);
                        glEnd();
                }
        }

}

Now, here is the real magic of the algorithm.

C:\Documents and Settings\Ronald\My Documents\dead\classes\raytrace.cpp //---------------------------------------------------------------------------

#include "raytrace.h"

vector  RayTrace(vector s,vector u,int depth,
                         objetos *objects,vector background, luz *ampolleta){
        vector q,qq,q2;  // Puntos de rebote
        q.invalid=1;
        vector n,rv,t,r; // Vectores Importantes
        vector shadow_feeler[N_LIGHTS];
        int deltai[N_LIGHTS],deltaprimai[N_LIGHTS];
        float dist_foco;
        vector color;
        objetos * current;
        objetos * colision;
        colision = 0;
        objetos * current2;
        current =  objects;
        float sqDistQanterior;
        while (current->next){
                qq = current->Intersection(s,u);
                if (!qq.invalid) {
                        if(!q.invalid){
                                if(sqDistQanterior>(qq-s).sqNorma()){
                                        q = qq;
                                        sqDistQanterior=(q-s).sqNorma();
                                        colision = current;
                                }
                        }
                        else{
                                q = qq;
                                sqDistQanterior=(q-s).sqNorma();
                                colision = current;
                        }
                }
        current = current->next;
        }
        qq = current->Intersection(s,u);
        if (!qq.invalid) {
                        if(!q.invalid){
                                if(sqDistQanterior>(qq-s).sqNorma()){
                                        q = qq;
                                        sqDistQanterior=(q-s).sqNorma();
                                        colision = current;
                                }
                        }
                        else{
                                q = qq;
                                sqDistQanterior=(q-s).sqNorma();
                                colision = current;
                        }
                }

                if(!colision)
                        return background;

                if ( !(q.invalid)){ // Hay Interseccion en q
                         n = colision->Normal(q);
                         for (int i = 0; i < N_LIGHTS; i++) {
                                 // Shadow Feeler
                                 shadow_feeler[i] = ampolleta[i].position-q;
                                 dist_foco = shadow_feeler[i].sqNorma();
                                 shadow_feeler[i].Normalize();
                                 ampolleta[i].lvector = shadow_feeler[i];
                                 current2 =  objects;
                                 while(current2->next){
                                        q2 = current2->Intersection(q,shadow_feeler[i]);
                                        if( !(q2.invalid)){ // Intersecta el SF
                                                if ((q2-q).sqNorma()< dist_foco){ // Objeto Bloquea la luz
                                                        deltai[i]=0;
                                                        deltaprimai[i]=0;
                                                }
                                        }else{
                                                if(shadow_feeler[i]*n>0){
                                                        deltai[i]=1;
                                                        deltaprimai[i]=0;
                                                }
                                                else{
                                                        deltai[i]=0;
                                                        deltaprimai[i]=1;
                                                }
                                        }

                                        current2 = current2->next;
                                   }
                                 q2 = current2->Intersection(q,shadow_feeler[i]);
                                        if( !(q2.invalid)){ // Intersecta el SF
                                                if ((q2-q).sqNorma()< dist_foco){ // Objeto Bloquea la luz
                                                        deltai[i]=0;
                                                        deltaprimai[i]=0;
                                                }
                                        }
                                        else {
                                        if(shadow_feeler[i]*n>0){
                                                        deltai[i]=1;
                                                        deltaprimai[i]=0;
                                                }
                                                else{
                                                        deltai[i]=0;
                                                        deltaprimai[i]=1;
                                                }
                                        }
                           }
                          rv= u - n*(u*n)*2;
                          rv.Normalize();
                          t = CalcTransmissionDirecction(u*(-1),n,colision->eta);
                          t.Normalize();
                         // Set Color
                         color  = ILocal(ampolleta, // Light Intensities  & light vector
                          colision->Ka, colision->Kd, colision->Ks, colision->Kdt, colision->Kst, // Material Propeties
                           deltai,  deltaprimai,  // From Shadow Feelers
                          n, rv, t, // vectors
                          colision->f); //<- producto escalar
                        /*  if(colision->textureON) {
                          int eu,ev;
                          float theta,phi;
                          phi = asin((q.y-(((esfera*)colision)->origen.y))/sqrt(((esfera*)colision)->sqR));
                          theta = (M_PI/2)+atan((q.x-(((esfera*)colision)->origen.x))/(q.z-(((esfera*)colision)->origen.z)));
                          ev = (int)(255*(theta/(2*M_PI)));
                          eu = (int)(255*(phi/M_PI +0.5));
                          color =  color/colision->textura[eu][ev];
                          color.x = color.x/255;
                          color.y = color.y/255;
                          color.z = color.z/255;

                          }*/

                          if (depth == 0){
                                        return color;
                          }
                          if (colision->Krg.x != 0 || colision->Krg.y != 0 || colision->Krg.z != 0){
//                                        r = u - n*(u*n)*2;
//                                        r.Normalize();
                                        color = color + RayTrace(q,rv,depth-1,objects,background,ampolleta)/colision->Krg;
                          }
                          if (colision->Ktg.x != 0 || colision->Ktg.y != 0 ||colision->Ktg.z != 0) {
                                        color = color + RayTrace(q,t,depth-1,objects,background, ampolleta)/colision->Ktg;

                          }
                }
  return color;
}

vector CalcTransmissionDirecction(vector v, vector n,float eta){
        vector tlat;
        float sinSq;
        tlat = n*(v*n)-v;
        tlat.x = tlat.x/eta; tlat.y = tlat.y/eta; tlat.z = tlat.z/eta;
        sinSq = tlat.sqNorma();     // sin^2(theta)
        if (sinSq > 1) {
                 tlat.invalid=1// Total internal reflection
                 return tlat;
        }
        return tlat - n*sqrt(1-sinSq);
}



//---------------------------------------------------------------------------

The Shots

 


Download