SColor SColor::mult(SColor other) { SColor c; c.R(R() * other.R()); c.G(G() * other.G()); c.B(B() * other.B()); return c; }
SColor RayTracer::calculateShadowScalar(Light <, Intersection &in) { // cout << in.toString() << endl; Vect p = lt.getPos(); Vect ori = in.calculateIntersectionPoint();// + in.calculateSurfaceNormal().linearMult(0.0001f); Vect dir; if (lt.getType() == DIRECTIONAL_LIGHT) { dir = lt.getDir().invert(); } else { dir = p - ori; dir.normalize(); } ori = ori + dir.linearMult(0.001f); Ray shdw(ori, dir); Intersection ins = scene->calculateRayIntersection(shdw); Material *mat = ins.getMaterial(); if (!ins.hasIntersected()) { // The point is in direct light return SColor(1, 1, 1); } else if (mat->getTransparency() <= 0.00000001) { // The material is fully opaque Vect pos = ins.calculateIntersectionPoint(); if (lt.getType() == DIRECTIONAL_LIGHT || ori.euclideanDistance(pos) < ori.euclideanDistance(lt.getPos())) { // The ray intersects with an object before the light source return SColor(0, 0, 0); } else { // The ray intersects with an object behind the lightsource // or a direction light, thus fully in light return SColor(1, 1, 1); } } else { // The shape is transparent // Normalize the color for this material, and recursively trace for other // transparent objects SColor Cd = mat->getDiffColor(); float m = max(Cd.R(), max(Cd.G(), Cd.B())); Cd.R(Cd.R()/m); Cd.G(Cd.G()/m); Cd.B(Cd.B()/m); SColor Si = Cd.linearMult(mat->getTransparency()); return Si.linearMult(calculateShadowScalar(lt, ins)); } }
RayBuffer RayTracer::traceRays() { // #pragma omp parallel for for (uint y = 0; y < HEIGHT; y++) { // #pragma omp parallel for for (uint x = 0; x < WIDTH; x++) { Ray r = computeRay(x, y); Intersection in = scene->calculateRayIntersection(r); SColor c = shadeIntersection(in, depth); PX_Color color; color.R = (uint8_t) (255 * c.R()); color.G = (uint8_t) (255 * c.G()); color.B = (uint8_t) (255 * c.B()); buffer.setPixel(x, y, color); } } return buffer; }