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:
- Trace a ray from the observer and find the collision point for the fist object on the screen.
- 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