Colour Raytracer::getColorFromRay( const Matrix4x4& viewToWorld, const Point3D& imagePlane, const Point3D& eye) #endif { // create ray from eye to place in image plane Ray3D ray; ray.origin = viewToWorld * imagePlane; ray.dir = ray.origin - eye; ray.dir.normalize(); #if _DEBUG // keep track of where the ray shot out from... to help with debugging later on ray.y = i; ray.x = j; #endif Colour col; //If Depth of field is ON, also shoot few random rays around the campera pin hole pixel to approximate depth of field //http://ray-tracer-concept.blogspot.ca/2011/12/depth-of-field.html if (DEPTH_OF_FIELD_FLAG) { //generate NUM_RAYS random rays around the position // printf(" >>>>>>> ADDING DEPTH OF FIELD <<<<<<<<< \n"); for (int di = 0; di < NUM_RAYS; di++) { //generate a random number within 5 pixel radius float du = rand()/float(RAND_MAX+1);//generating random number float dv = rand()/float(RAND_MAX+1); // creating new camera position(or ray start using jittering) float x = imagePlane[0] + du; float y = imagePlane[1] + dv; float z = imagePlane[2]; //set the new pixel at the imagePlane Point3D blurr_img = Point3D(x, y, z); ray.origin = viewToWorld * blurr_img; ray.dir = ray.origin - eye; ray.dir.normalize(); // create ray from eye to place in image plane col = col + shadeRay(ray, 0, 0); } //normalize for NUM_RAYS pixel colours double col_r = col[0]/ NUM_RAYS; double col_g = col[1]/ NUM_RAYS; double col_b = col[2]/ NUM_RAYS; col = Colour(col_r, col_g, col_b); } else { // shade pixel based on ray data col = shadeRay(ray, 0, 0); } return col; }
Colour Raytracer::anti_aliasing_helper(Point3D img_plane, Matrix4x4 view_to_world) { Point3D origin(0,0,0); Ray3D ray; ray.origin = view_to_world * origin; ray.dir = view_to_world * img_plane - ray.origin; ray.dir.normalize(); return shadeRay(ray); }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, char* fileName ) { Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); //std::cout<<viewToWorld<<std::endl; // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { Colour col; if (antiAliasing) { col = anti_aliasing(viewToWorld, width, height, factor, i, j); } else { // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; imagePlane[2] = -1; Vector3D _dir (imagePlane[0],imagePlane[1],imagePlane[2]); Vector3D dir = viewToWorld * _dir; origin = viewToWorld * origin;; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. Ray3D ray; ray.origin = origin; ray.dir = dir; Colour col = shadeRay(ray); //std:: cout << "i:" <<i << "j:" << j <<"Hit: "<<ray.intersection.none<<std::endl; } _rbuffer[i*width+j] = int(col[0]*255); _gbuffer[i*width+j] = int(col[1]*255); _bbuffer[i*width+j] = int(col[2]*255); } } flushPixelBuffer(fileName); }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, char* fileName) { Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { //perform antialiasing with a factor of 4 so ray is computed 4 times at a pixel //and multiplied by factor 1/4 and summed together for antialiased image for(float fragmenti = i; fragmenti < i + 1.0f; fragmenti += 0.5f){ for(float fragmentj = j; fragmentj < j + 1.0f; fragmentj += 0.5f){ // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + fragmentj)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + fragmenti)/factor; imagePlane[2] = -1; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. //multiply each ray by 1/4 float coef = 0.25f; Ray3D ray; // want ray to be in world frame ray.origin = viewToWorld*origin; ray.dir = viewToWorld*(imagePlane-origin); ray.dir.normalize(); Colour col = shadeRay(ray); //now sum the total contributions from 4 rays per pixel _rbuffer[i*width+j] += int(col[0]*255*coef); _gbuffer[i*width+j] += int(col[1]*255*coef); _bbuffer[i*width+j] += int(col[2]*255*coef); } } } } flushPixelBuffer(fileName); }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, std::string fileName ) { computeTransforms(_root); Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0., 0., 0.); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; imagePlane[2] = -1; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. // ray -> world space Point3D rayOriginWorld = viewToWorld * imagePlane; Vector3D rayDir = imagePlane - origin; Vector3D rayDirWorld = viewToWorld * rayDir; Ray3D ray; ray.origin = rayOriginWorld; ray.dir = rayDirWorld; ray.dir.normalize(); // pixel colour Colour col = shadeRay(ray); _rbuffer[i*width+j] = int(col[0]*255); _gbuffer[i*width+j] = int(col[1]*255); _bbuffer[i*width+j] = int(col[2]*255); } } flushPixelBuffer(fileName); }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, char* fileName, char mode ) { Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; imagePlane[2] = -1; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. /////////////////////// OUR CODE /////////////////////////////// Vector3D d = Vector3D(imagePlane[0], imagePlane[1], imagePlane[2]); d = viewToWorld*d; origin = viewToWorld*origin; Ray3D ray = Ray3D( origin , d ); if (mode == 'd'){ (*(ray.intersection.mat)).specular = Colour(0,0,0); } Colour col; col = shadeRay(ray, mode); /////////////////////// OUR CODE /////////////////////////////// _rbuffer[i*width+j] = int(col[0]*255); _gbuffer[i*width+j] = int(col[1]*255); _bbuffer[i*width+j] = int(col[2]*255); } } flushPixelBuffer(fileName); }
Colour Raytracer::shadeRay( Ray3D& ray ) { Colour col(0.0, 0.0, 0.0); traverseScene(_root, ray); // Don't bother shading if the ray didn't hit // anything. if (!ray.intersection.none) { computeShading(ray); // You'll want to call shadeRay recursively (with a different ray, // of course) here to implement reflection/refraction effects. float dampFactor = 0.0; // Calculate reflection ray Vector3D N = ray.intersection.normal; Vector3D D = ray.dir; Vector3D reflectionDir = -2*(D.dot(N))*N + D; reflectionDir.normalize(); Point3D reflectionOrigin = ray.intersection.point + 0.01*reflectionDir; Ray3D reflectionRay = Ray3D(reflectionOrigin, reflectionDir); // calculate shade of reflected ray shadeRay(reflectionRay); // limit effective distance of reflections if (reflectionRay.intersection.t_value > 10.0 || reflectionRay.intersection.t_value <= 0.0) { col = ray.col; } else { dampFactor = fabs(1.0/reflectionRay.intersection.t_value); // contraint dampFactor to 0-0.9 dampFactor = fmax(0, fmin(dampFactor,0.9)); // Set colour to include reflection col = ray.col + dampFactor*reflectionRay.col; } col.clamp(); } return col; }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, char* fileName ) { Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; imagePlane[2] = -1; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. Point3D ray_origin = viewToWorld * imagePlane; Vector3D ray_dir = ray_origin - eye; Ray3D ray(ray_origin, ray_dir); Colour col = shadeRay(ray); _rbuffer[i*width+j] = int(col[0]*255); _gbuffer[i*width+j] = int(col[1]*255); _bbuffer[i*width+j] = int(col[2]*255); } } flushPixelBuffer(fileName); }
Colour Raytracer::shadeRay( Ray3D& ray, int depth ) { Colour col(0.0, 0.0, 0.0); traverseScene(_root, ray); Ray3D r; // Don't bother shading if the ray didn't hit // anything. if (!ray.intersection.none) { computeShading(ray); col = ray.col; if (depth > 1) { if (ray.intersection.mat->specular_exp > 20) { Vector3D n = ray.intersection.normal; n.normalize(); r.origin = ray.intersection.point; Vector3D refl = (-2 * ray.dir.dot(n)) * n + ray.dir; r.dir = refl; r.dir.normalize(); r.col = shadeRay(r, depth-1); col = col + r.col; col.clamp(); } } } // You'll want to call shadeRay recursively (with a different ray, // of course) here to implement reflection/refraction effects. return col; }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, int AA_level, char* fileName, char renderStyle ) { Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(_scrHeight)/2)/tan(fov*M_PI/360.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); /** * Extension: Anti-aliasing level via supersampling method * Algorithm: * Generate an image of dimensions equal to a multiple of the original * dimensions (as specified by the AA level) * Then sample individual pixels and average them to compose a pixel * on the actual screen */ _aaLevel = AA_level; initSuperPixelBuffer(); /// A little print for the user fprintf(stderr, "Rendering %dx%d scene, AA-level %d\n", _scrWidth, _scrHeight, _aaLevel); int superi, superj; double offi, offj; // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { // Prepare to supersample for anti aliasing for (int m = 0; m < _aaLevel; m++) { for (int n = 0; n < _aaLevel; n++) { // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; offj = double(1)/(0.5 * _aaLevel) + double(n)/_aaLevel; offi = double(1)/(0.5 * _aaLevel) + double(m)/_aaLevel; imagePlane[0] = (-double((_scrWidth))/2 + offj + j)/factor; imagePlane[1] = (-double((_scrHeight))/2 + offi + i)/factor; imagePlane[2] = -1; // Create the transformed ray and shoot it out (shadeRay) Vector3D pixelVector = Vector3D(imagePlane[0], imagePlane[1], imagePlane[2]); Vector3D transformedPixelVector = viewToWorld * pixelVector; Point3D transformedOrigin = viewToWorld * origin; Ray3D ray = Ray3D(transformedOrigin, transformedPixelVector); //Check for scene render style Colour col = shadeRay(ray, renderStyle); superi = i*_aaLevel + m; superj = j*_aaLevel + n; _superrbuffer[superi*(_aaLevel*_scrWidth)+superj] = int(col[0]*255); _supergbuffer[superi*(_aaLevel*_scrWidth)+superj] = int(col[1]*255); _superbbuffer[superi*(_aaLevel*_scrWidth)+superj] = int(col[2]*255); } }//End supersampling loop } }//finsihed pixel loop // Now average out the pixels from the super buffer (supersampling) factor = double(1)/(_aaLevel * _aaLevel); unsigned long rtemp; unsigned long gtemp; unsigned long btemp; for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { rtemp = 0; gtemp = 0; btemp = 0; for (int m = 0; m < _aaLevel; m++) { superi = i*_aaLevel + m; for (int n = 0; n < _aaLevel; n++) { superj = j*_aaLevel + n; rtemp += _superrbuffer[superi*(_aaLevel*_scrWidth)+superj]; gtemp += _supergbuffer[superi*(_aaLevel*_scrWidth)+superj]; btemp += _superbbuffer[superi*(_aaLevel*_scrWidth)+superj]; } } _rbuffer[i*_scrWidth+j] = factor * rtemp; _gbuffer[i*_scrWidth+j] = factor * gtemp; _bbuffer[i*_scrWidth+j] = factor * btemp; } } flushPixelBuffer(fileName); }
Colour Raytracer::shadeRay( Ray3D& ray, char renderStyle ) { Colour col(0.0, 0.0, 0.0); traverseScene(_root, ray); // Don't bother shading if the ray didn't hit // anything. if (!ray.intersection.none) { //computeShading(ray); if (renderStyle != 's') { computeShading(ray, renderStyle); col = ray.col; #ifdef USE_REFLECTIONS if ((ray.intersection.mat->reflectivity >= 0.01) && (ray.reflections < MAX_REFLECTIONS) && (renderStyle != 'd')) { // emit another ray Vector3D n = ray.intersection.normal; n.normalize(); Vector3D d = ray.dir; d.normalize(); double dot = n.dot(d); Vector3D newdir = d - (2 * dot * n); Ray3D newRay = Ray3D(ray.intersection.point + 0.01*newdir, newdir, ray.reflections+1, ray.refractions, ray.cLight); Colour secondaryColour = shadeRay(newRay, renderStyle); double ref = ray.intersection.mat->reflectivity; col = (1-ref)*ray.col + ref*secondaryColour; } else { col = ray.col; } #else col = ray.col; #endif // Check for refractions // Don't check for refractions of reflected rays #ifdef USE_REFRACTIONS if((ray.intersection.mat->transitivity >= 0.1) && (ray.refractions < MAX_REFRACTIONS) && (renderStyle != 'd')) { double c1 = ray.cLight; double c2 = ray.intersection.mat->cLight; if (ray.cLight < 0.99) { //Ray leaves object to air/vacuum c2= 1; } Vector3D n = ray.intersection.normal; n.normalize(); Vector3D d = ray.dir; d.normalize(); double dot = n.dot(d); Vector3D reflDir = d - (2 * dot * n); reflDir.normalize(); //Now determine refraction direction //Depends on reflDir, c1, c2, n, as specified in the relation below double theta1 = acos( n.dot(-d) ); if(dot > 0 ) { //Ray is leaving object theta1 = acos( n.dot(d) ); } double theta2 = asin(c2*sin(theta1)/c1); //Check for critical angle // Compute refraction direction Vector3D refractDir = (c2/c1)*ray.dir + ( (c2/c1)*cos(theta1) - cos(theta2))*n; if(dot > 0 ) { //Ray is leaving object =====================changed sign refractDir = (c2/c1)*ray.dir - ( (c2/c1)*cos(theta1) - cos(theta2))*n; } refractDir.normalize(); Ray3D refractRay = Ray3D(ray.intersection.point + 0.0001*refractDir, refractDir,ray.reflections, ray.refractions+1, c2 ); Colour colRefract = shadeRay(refractRay, renderStyle); double matTran = ray.intersection.mat->transitivity; if(!refractRay.intersection.none) { //Refracted ray does not go off into space col = (1-matTran)*col + matTran*colRefract; } }//end of refractions #endif }//End of check if(renderStyle != 's') else { //renderStyle == 's' col = (*(ray.intersection.mat)).diffuse; } }//End of check if (!ray.intersection.none) return col; }// End of shadeRay
gml::vec3_t Scene::shadeRay(const RayTracing::Ray_t &ray, RayTracing::HitInfo_t &hitinfo, const int remainingRecursionDepth) const { // TODO! // Calculate the shade/radiance/color of the given ray. Return the calculated color // - Information about the ray's point of nearest intersection is located // in 'hitinfo' // - If remainingRecursionDepth is 0, then _no_ recursive rays (mirror or indirect lighting) should be cast // Note: You will have to set up the values for a RayTracing::ShaderValues object, and then // pass the object to a shader object to do the appropriate shading. // Use m_shaderManager.getShader() to get an appropriate Shader object for shading // the point based on material properties of the object intersected. // When implementing shadows, then the direct lighting component of the // calculated ray color will be black if the point is in shadow. //ml::vec3_t shade(0.5, 0.5, 0.5); //RayTracing::ShaderValues sv(hitinfo.objHit->getMaterial()); // Note: For debugging your rayIntersection() function, this function // returns some non-black constant color at first. When you actually implement // this function, then initialize shade to black (0,0,0). gml::vec3_t shade(0.0, 0.0, 0.0); gml::vec2_t texCoord; gml::vec3_t normal; hitinfo.objHit->hitProperties(hitinfo, normal, texCoord); RayTracing::ShaderValues shaderVal(hitinfo.objHit->getMaterial()); shaderVal.n = normal; shaderVal.p = gml::add(ray.o, gml::scale(hitinfo.hitDist, ray.d)); shaderVal.e = gml::normalize(gml::scale(-1.0f, ray.d)); shaderVal.tex = texCoord; shaderVal.lightDir = gml::normalize(gml::sub(gml::extract3(m_lightPos), shaderVal.p)); shaderVal.lightRad = m_lightRad; float distToLight = gml::length(gml::sub(gml::extract3(m_lightPos), shaderVal.p)); // test if in shadow RayTracing::Ray_t shadowRay; shadowRay.o = shaderVal.p; shadowRay.d = shaderVal.lightDir; if (!shadowsRay(shadowRay, 0.001, distToLight)) { // direct lighting shade = m_shaderManager.getShader(hitinfo.objHit->getMaterial())->shade(shaderVal); } else { shade = gml::vec3_t(0,0,0); } // Only proceed if the recursion depth limit has not been met. if (remainingRecursionDepth > 0) { // Mirror checks, and shading. if (hitinfo.objHit->getMaterial().isMirror()) { // Ray for mirrors. RayTracing::Ray_t mirrorRay; mirrorRay.o = shaderVal.p; mirrorRay.d = gml::normalize(gml::scale(-1, gml::reflect(ray.d, normal))); RayTracing::HitInfo_t mirrorHitInfo; // If intersection, get the mirror shading color and apply it. if (this->rayIntersects(mirrorRay, 0.001f, FLT_MAX, mirrorHitInfo)) { gml::vec3_t mirrorShade = shadeRay(mirrorRay, mirrorHitInfo, remainingRecursionDepth - 1); shade = gml::add(shade, gml::mul(hitinfo.objHit->getMaterial().getMirrorRefl(), mirrorShade)); } } // Setup indirect lighting. RayTracing::Ray_t indirectRay; indirectRay.o = shaderVal.p; indirectRay.randomDirection(shaderVal.n); RayTracing::HitInfo_t indirectHitInfo; // If intersection, apply indirect ray for indirect lighting. if (this->rayIntersects(indirectRay, 0.001f, FLT_MAX, indirectHitInfo)) { shaderVal.lightDir = indirectRay.d; shaderVal.lightRad = shadeRay(indirectRay, indirectHitInfo, remainingRecursionDepth - 1); gml::vec3_t indirectShade = m_shaderManager.getShader(hitinfo.objHit->getMaterial())->shade(shaderVal); // Add together to the cumulative color. shade = gml::add(shade, indirectShade); } } // Note: For debugging your rayIntersection() function, this function // returns some non-black constant color at first. When you actually implement // this function, then initialize shade to black (0,0,0). // Return the cumulative color for the point. return shade; }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, const char* fileName ) { /*****************anti-aliasing************************/ Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); Colour totalCol(0.0,0.0,0.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); scfCache(_root); // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { //anti-aliasing, each pixel can have 4 rays, the pixel color determined by the avgerage for(double a = i; a < i+1 ; a += 0.5){ for(double b = j; b < j+1;b += 0.5){ // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + b)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + a)/factor; imagePlane[2] = -1; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. Point3D originW = viewToWorld * imagePlane; Vector3D directionW = viewToWorld * (imagePlane -origin); directionW.normalize(); Ray3D ray(originW, directionW); Colour col = shadeRay(ray,0,0); //each ray contributed 0.25 color to the final rending color for the pixel _rbuffer[i*width+j] += int(col[0]*255*0.25); _gbuffer[i*width+j] += int(col[1]*255*0.25); _bbuffer[i*width+j] += int(col[2]*255*0.25); } } } } /********************anti-aliasing**************************/ // Matrix4x4 viewToWorld; // _scrWidth = width; // _scrHeight = height; // double factor = (double(height)/2)/tan(fov*M_PI/360.0); // // initPixelBuffer(); // viewToWorld = initInvViewMatrix(eye, view, up); // scfCache(_root); // // Construct a ray for each pixel. // for (int i = 0; i < _scrHeight; i++) { // for (int j = 0; j < _scrWidth; j++) { // // Sets up ray origin and direction in view space, // // image plane is at z = -1. // Point3D origin(0, 0, 0); // Point3D imagePlane; // imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; // imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; // imagePlane[2] = -1; // // // TODO: Convert ray to world space and call // // shadeRay(ray) to generate pixel colour. // // //Vector3D dir = imagePlane-origin; // Ray3D ray(origin,imagePlane-origin); // /*my dode here*/ // ray.origin = viewToWorld*ray.origin; // ray.dir = viewToWorld*ray.dir; // ray.dir.normalize(); // Colour col = shadeRay(ray,0,0);//the original is shadeRay(ray) // // _rbuffer[i*width+j] = int(col[0]*255); // _gbuffer[i*width+j] = int(col[1]*255); // _bbuffer[i*width+j] = int(col[2]*255); // } // } flushPixelBuffer(fileName); }
// After intersection, calculate the colour of the ray by shading it // with all light sources in the scene. Colour Raytracer::shadeRay( Ray3D& ray,int times_reflec,int times_refrac ) {//(reflection)* shadeRay Colour col(0.0, 0.0, 0.0); traverseScene(_root, ray); //for reflextion here // Don't bother shading if the ray didn't hit // anything. // if (!ray.intersection.none) { // computeShading(ray); // col = ray.col; // } // return col; /*******************Reflection&Refraction********************/ Colour reflColour(0.0, 0.0, 0.0); Colour refraColour; if (!ray.intersection.none) { computeShading(ray); col = ray.col*Colour((1-ray.intersection.mat->transparency_coef), (1-ray.intersection.mat->transparency_coef), (1-ray.intersection.mat->transparency_coef)); //for flection if(times_reflec < 3 && ray.intersection.mat->reflect_coef != 0&&ray.intersection.mat->transparency_coef==0){ Ray3D reflect_ray; reflect_ray.dir = ray.dir - (2 * (ray.dir.dot(ray.intersection.normal)) * ray.intersection.normal); reflect_ray.dir.normalize(); reflect_ray.origin = ray.intersection.point+(1e-6) * reflect_ray.dir; times_reflec = times_reflec + 1; //Colour refl = shadeRay(reflect_ray,times); reflColour = reflColour + ray.intersection.mat->reflect_coef*shadeRay(reflect_ray,times_reflec,times_reflec); } //for refraction if(times_refrac<3&&ray.intersection.mat->transparency_coef>0){ Ray3D refraction_ray; double n; Vector3D N =ray.intersection.normal; if(ray.intersection.insideCrash){ n =ray.intersection.mat->R_index; N = (-1)*N; }else{ n=1/ray.intersection.mat->R_index; } double cosI = (-1.0)*N.dot(ray.dir); double cosT2 = 1.0 - (n*n)*(1.0- cosI*cosI ); if(cosT2>0.0){//whether can have refraction or not double cosT = sqrt(cosT2); // double tmp1 = sqrt(1.0-(R_index*ray.dir.dot(ray.intersection.normal)*ray.dir.dot(ray.intersection.normal))); refraction_ray.dir =n*ray.dir+(n*cosI-cosT)*N; refraction_ray.dir.normalize(); //refraction_ray.dir =n*ray.dir+(n*tmp2-tmp1)*(ray.intersection.normal); refraction_ray.origin = ray.intersection.point+(1e-6)*refraction_ray.dir; times_refrac++; refraColour = refraColour+ray.intersection.mat->transparency_coef*shadeRay(refraction_ray, times_refrac, times_refrac); } } } col = col + reflColour+refraColour; col.clamp(); return col; /***************END OF Reflection&Refraction***********************/ /*******************Reflection******************** Colour reflColour(0.0, 0.0, 0.0); if (!ray.intersection.none) { computeShading(ray); col = ray.col; if(times < 3 && ray.intersection.mat->reflect_coef != 0){ Ray3D reflect_ray; reflect_ray.dir = ray.dir - (2 * (ray.dir.dot(ray.intersection.normal)) * ray.intersection.normal); reflect_ray.dir.normalize(); reflect_ray.origin = ray.intersection.point+(1e-6) * reflect_ray.dir; times = times + 1; //Colour refl = shadeRay(reflect_ray,times); reflColour = reflColour + ray.intersection.mat->reflect_coef*shadeRay(reflect_ray,times); } } col = col + reflColour; col.clamp(); return col; ***************END OF Reflection***********************/ /*******************Glossy******************** Colour reflColour(0.0, 0.0, 0.0); if (!ray.intersection.none) { computeShading(ray); col = ray.col; if (times < 3 && ray.intersection.mat->reflect_coef != 0) { Ray3D reflect_ray; reflect_ray.dir = (ray.dir - ((2*(ray.dir.dot(ray.intersection.normal)))*ray.intersection.normal)); reflect_ray.dir.normalize(); reflect_ray.origin = ray.intersection.point + 1e-6*reflect_ray.dir; double L = 0.5; // roughness for (int i = 0; i < 4; i++) { //r(i) = normalize(r+(0.5-xi)Lu + (0.5-yi)Lv) double xi = (double)rand() / (double)RAND_MAX; double yi = (double)rand() / (double)RAND_MAX; reflect_ray.dir[0] += (0.5-xi)*L; reflect_ray.dir[1] += (0.5-yi)*L; reflect_ray.dir.normalize(); times = times + 1; reflColour = reflColour + ray.intersection.mat->reflect_coef*shadeRay(reflect_ray , times); } reflColour = (1.0/4.0)*reflColour; } col = col + reflColour; col.clamp(); } return col; ****************END OF GLOSSY********************************/ // You'll want to call shadeRay recursively (with a different ray, // of course) here to implement reflection/refraction effects. ........................... }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, char* fileName, int aa, int fl, bool dof ) { Matrix4x4 viewToWorld; width = width * aa; height = height * aa; double factor = (double(height)/2)/tan(fov*M_PI/360.0); viewToWorld = initInvViewMatrix(eye, view, up); initAABuffer(aa, width, height); _scrWidth = width / aa; _scrHeight = height / aa; initPixelBuffer(); // Construct a ray for each pixel. for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; imagePlane[2] = -1; Ray3D ray; ray.origin = viewToWorld * origin; ray.dir = viewToWorld * imagePlane - ray.origin; ray.dir.normalize(); Colour col(0,0,0); //implement depth of field if true if (dof == true) { //generate a point in the scene as part of the focal plane Vector3D pointAimed = (ray.origin + fl * ray.dir) - Point3D(0,0,0); float r = 1; Colour pc(0,0,0); for (int px=0; px < 15; px++) { float du = ((float) rand())/(float(RAND_MAX)); float dv = ((float) rand())/(float(RAND_MAX)); //x and y axis of camera/eye Vector4D u = viewToWorld.getColumn(1); Vector4D v = viewToWorld.getColumn(0); //convert them to 3d vectors; Vector3D u2(u[0],u[1],u[2]); Vector3D v2(v[0],v[1],v[2]); //convert ray.origin to vector for vector operation; Vector3D tempv(ray.origin[0], ray.origin[1], ray.origin[2]); //generate random point around the eye (vector is used for operation) Vector3D eyev = tempv - (r/2)*u2 - (r/2)*v2 + r*(du)*u2 + r*(dv)*v2; //generate a ray from random point to pointAimed Ray3D dovr; dovr.dir = pointAimed - eyev; dovr.origin = Point3D(eyev[0], eyev[1], eyev[2]); dovr.dir.normalize(); //bounce ray into the scene and get its color Colour dovCol = shadeRay(dovr, 2); pc = pc + dovCol; } //average the pixel colors to get the blurriness effect col = (1/15.0) * pc; } else { col = shadeRay(ray, 2); } col.clamp(); if (aa == 1) { _rbuffer[i*width+j] = int(col[0]*255); _gbuffer[i*width+j] = int(col[1]*255); _bbuffer[i*width+j] = int(col[2]*255); } else { re[i*width+j] = int(col[0]*255); gr[i*width+j] = int(col[1]*255); bl[i*width+j] = int(col[2]*255); } } } if (aa == 1) { flushPixelBuffer(fileName); } else { aarender(width, height, aa, fileName); delete re; delete gr; delete bl; } }
Colour Raytracer::shadeRay( Ray3D& ray, int reflectionDepth, int refractionDepth ) { Colour col(0.0, 0.0, 0.0); traverseScene(_root, ray); // Don't bother shading if the ray didn't hit // anything. if (REFRACTION_FLAG_DEBUG) { printf("\n\n checking intersection \n"); printf(" incident ray: (%f, %f, %f) \n", ray.dir[0], ray.dir[1], ray.dir[2]); } Intersection inter = ray.intersection; if ( !inter.none ) { computeShading(ray); if (REFRACTION_FLAG_DEBUG) { printf("\n\n ---------------------- INTERSECTION WITH OBJECT ------------------------------ \n\n"); } //Spawn a ray for reflection if ( reflectionDepth < getReflDepth() ) { Vector3D n = inter.normal; Vector3D de = -ray.dir; Vector3D m = 2 * de.dot(n) * n - de; // reflect across normal // http://www.cdf.toronto.edu/~moore/csc418/Notes/Phong.pdf // reflection if ( inter.mat->refl_amt > 0.0f ) { if (REFRACTION_FLAG_DEBUG) { printf("\n\n ........ DOING REFLECTION ........ \n"); } Ray3D refl_ray; refl_ray.origin = inter.point;// + (DBL_0_UPPER * m); refl_ray.dir = m; Colour rCol(0.0, 0.0, 0.0); rCol = shadeRay(refl_ray, reflectionDepth + 1, refractionDepth); ray.col = ray.col + (inter.mat->refl_amt * rCol); } // Spawn a seperate ray for refraction if ( inter.mat->transparency > 0.0f ) { double th_1 = std::abs(de.dot(n)); double c1, c2; if ( th_1 >= 0 ) { c1 = inter.mat->IOR; c2 = ray._cur_speed; ray._cur_speed = c1; } else { c2 = inter.mat->IOR; c1 = ray._cur_speed; ray._cur_speed = c2; } double IOR = c2 / c1; // double IOR = 1; // will make it transparent, for testing double th_2 = sqrt(1.0 - (IOR * IOR) * (1.0 - (th_1 * th_1))); Ray3D refr_ray; refr_ray.dir = -de + IOR * (th_1 * n) + (-th_2 * n); refr_ray.origin = (inter.point) + (DBL_EPSILON * refr_ray.dir); Colour rCol(0.0, 0.0, 0.0); rCol = shadeRay(refr_ray, reflectionDepth + 1, refractionDepth + 1); ray.col = ray.col + (inter.mat->transparency * rCol); } } col = ray.col; } else { // env map if ( getEnvMapMode() == ENV_MAP_CUBE_SKYBOX ) { col = getEnvMap().getColorForRay(ray.dir); } } col.clamp(); return col; }