struct Ray_Tracer_Code {
Welcome to my Ray Tracer Code page. Here you can see a few snippets of code that I wrote for a ray tracing graphics system.
The Ray Tracing system was built in 10 week class, and heavily uses 3D (linear algebra) math. More info in the system can be seen on its project page. Here you can see the code that draws a scene by shooting rays out of every pixel of the screen (Ray_Code_1), code that calculates reflection rays (Ray_Code_2) and shadows (Ray_Code_3).
Ray_Code_1: drawing a ray traced scene.
void scene::DrawScene(void) { int w = win->Width(); int h = win->Height(); double pixelW = windowW / w; double pixelH = windowH / h; if (bit != NULL) delete bit; bit = new Bitmap(*win, w, h); // Calculate the normalized view vector vector view = target - camera; view.normalize(); // Calculate the center of the window point center = camera + view * windowD; // Before we can use the up vector, we need to make sure // that it is perpendicular to the view vector, so we // Set up = up_(perp, view), the perpendicular component // of up with respect to the view vector up = up - dot(up, view) * view; // Normalize the up vector up.normalize(); // Now calculate the left vector vector left = cross(up, view); // Calculate the coordinates of pixel(0, 0) point upperLeft = center + up * (windowH - pixelW) / 2.0 + left * (windowW - pixelH) / 2.0; int t1 = clock(); for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { vector dx = -(pixelW * i) * left; vector dy = -(pixelH * j) * up; point screenP = upperLeft + dx + dy; ray r; r.p = camera; r.v = screenP - camera; rgb result = Trace(r); result.Normalize(); bit->Point(i, j, result.R(), result.G(), result.B()); } CopySceneToWindow(); } int t2 = clock(); cout << "Frame drawn in " << double(t2-t1) / CLOCKS_PER_SEC << endl; bit->Save("test.bmp"); }
Ray_Code_2: Shadow Calculations.
bool light::CalculateShadow(const intersection &inter, lightOutput &output) { const LinkedList<shape *> &shapes = inter.w->shapes; intersection tmp; double tLight; if (CanShadow() && inter.s->CanBeShadowed()) { ray r; r.v = output.L; r.p = inter.p + 1e-8*(dot(-inter.v, output.L)*output.L); // This allows you to compare the intersection t that you find with the // distance to the light. If the object is "behind" a pointlight // then it shouldn't shadow. Note: distant lights don't have position if (HasPosition()) tLight = pdistance(inter.p, GetPosition()) / output.L.length(); else tLight = DBL_MAX; for (shapes.MoveFirst(); !shapes.AtEnd(); shapes.MoveNext()) { tmp.w = inter.w; shape *s = shapes.GetCurrent(); if(s->CanShadow()) { if( !s->CalculateIntersection(r, tmp) ) continue; if( tmp.t > tLight ) continue; output.d *= .2; output.s = rgb::black; return true; } } } return false; }
Ray_Code_3: Reflection Calculations.
void phongMaterial::ReflectedColor(rgb &outA, rgb &outD, rgb &outS, LinkedList<class light *> &lights, const intersection &inter) { rgb diffuse, specular; rgb cA = inter.c; rgb cD = inter.c; lightOutput lightVal; outA = rgb::black; outD = rgb::black; outS = rgb::black; ListIter<light *> lightIter(lights); for (lightIter.MoveFirst(); !lightIter.AtEnd(); lightIter.MoveNext()) { lightIter.GetCurrent()->Illuminance(inter, lightVal); //always calculate the ambient light outA += cA*lightVal.a; //normalize the view vector view = inter.v; view.normalize(); //get the forward facing normal vector normal = inter.n; double VdotN = dot(inter.v, inter.n); if(VdotN > 0) normal = -normal; normal.normalize(); //Get the L vector vector L = lightVal.L; //Light L.normalize(); //if the light is facing the normal double LdotN = dot(L, normal); if( dot(-L,normal) < 0 ) { //R vector vector R = -L + 2*LdotN*normal; //Reflection //angle of refelection from the view //raised to the shininess in order to smooth out the value double RdotV = pow(dot(R, view), shininess); //calculate the Diffuse and Specular light outD += cD*lightVal.d*LdotN; outS += cS*lightVal.s*RdotV; } } }