/************************************************************************ * This is the recursive ray tracer - you need to implement this! * You should decide what arguments to use. ************************************************************************/ RGB_float recursive_ray_trace(Point &pos, Vector &ray, int num, bool inside=false) { IntersectionInfo end; const Object *s = getClosestObject(pos, ray, end); if (s == nullptr) { return background_clr; } Vector norm = s->getNormal(end); if (inside) { norm *= -1; } RGB_float color = phong(end.pos, ray, norm, s); if (num <= step_max) { Vector h; RGB_float ref({0,0,0}); RGB_float ract({0,0,0}); if (!inside && reflect_on) { h = vec_reflect(ray, norm); ref = recursive_ray_trace(end.pos, h, num + 1); } if (stochdiff_on) { RGB_float diff = {0,0,0}; std::default_random_engine generator; std::uniform_int_distribution<int> distribution(-10,10); for (int i = 0; i < STOCH_RAYS; ++i) { h = vec_reflect(ray, norm); h = RotateX(distribution(generator)) * RotateY(distribution(generator)) * RotateZ(distribution(generator)) * h; diff += recursive_ray_trace(end.pos, h, num+1); } diff /= 6; color += (diff*s->reflectance); } if (refract_on) { if (inside) { h = vec_refract(ray, norm, 1.5, 1); } else { h = vec_refract(ray, norm, 1, 1.5); } ract = recursive_ray_trace(end.pos, h, num + 1, !inside); } float reflectWeight = s->reflectance; float refractWeight = 0; if (refract_on && s->transparency > 0) { refractWeight = s->transparency; reflectWeight = (1-refractWeight)*s->reflectance; } color += (ref * reflectWeight + ract * refractWeight); } return color; }
/********************************************************************* * This function traverses all the pixels and cast rays. It calls the * recursive ray tracer and assign return color to frame * * You should not need to change it except for the call to the recursive * ray tracer. Feel free to change other parts of the function however, * if you must. *********************************************************************/ void ray_trace() { int i, j; float x_start = -0.5 * image_width; float y_start = -0.5 * image_height; RGB_float ret_color; Point cur_pixel_pos; Vector ray; // ray is cast through center of pixel cur_pixel_pos.x = x_start + 0.5 * x_grid_size; cur_pixel_pos.y = y_start + 0.5 * y_grid_size; cur_pixel_pos.z = image_plane; for (i=0; i<win_height; i++) { for (j=0; j<win_width; j++) { ray = get_vec(eye_pos, cur_pixel_pos); ret_color = recursive_ray_trace(ray, eye_pos, 0); if(supersampling_on) //supersampling { ret_color = supersample(cur_pixel_pos, ray, ret_color); } frame[i][j][0] = GLfloat(ret_color.r); frame[i][j][1] = GLfloat(ret_color.g); frame[i][j][2] = GLfloat(ret_color.b); cur_pixel_pos.x += x_grid_size; } cur_pixel_pos.y += y_grid_size; cur_pixel_pos.x = x_start; } }
/********************************************************************* * This function traverses all the pixels and cast rays. It calls the * recursive ray tracer and assign return color to frame * * You should not need to change it except for the call to the recursive * ray tracer. Feel free to change other parts of the function however, * if you must. *********************************************************************/ RGB_float supersample(Point cur_pixel_pos, Vector ray, RGB_float initial_color) { RGB_float ret_color = initial_color; Vector ss_ray; RGB_float ss_color = {0,0,0}; Point ss_pixel_pos; //first ray through center of pixel //ss_color = recursive_ray_trace(ray, eye_pos, 0); //set pixel to be supersampled to be the current pixel ss_pixel_pos = cur_pixel_pos; //supersample the 4 pixels with respect to x_grid_size and y_grid_size for(float dx = -x_grid_size/2; dx <= x_grid_size/2; dx+=x_grid_size){ for(float dy = -y_grid_size/2; dy <= y_grid_size/2; dy+=y_grid_size){ ss_pixel_pos.x = cur_pixel_pos.x + dx; ss_pixel_pos.y = cur_pixel_pos.y + dy; ss_ray = get_vec(eye_pos, ss_pixel_pos); ret_color = recursive_ray_trace(ss_ray, eye_pos, 0); ss_color = clr_add(ss_color, ret_color); //accumulate the colors from all ss rays } } ret_color = clr_scale(ss_color, 0.2); return ret_color; }
void rayThread(int i, int j, Point cur_pixel_pos, Vector ray, float x_grid_size, float y_grid_size) { RGB_float ret_color; RGB_float colors[5]; colors[0] = recursive_ray_trace(cur_pixel_pos, ray, 1); if (antialias_on) { cur_pixel_pos.x += x_grid_size / 2; cur_pixel_pos.y += y_grid_size / 2; colors[1] = recursive_ray_trace(cur_pixel_pos, ray, 1); cur_pixel_pos.y -= y_grid_size; colors[2] = recursive_ray_trace(cur_pixel_pos, ray, 1); cur_pixel_pos.x -= x_grid_size; colors[3] = recursive_ray_trace(cur_pixel_pos, ray, 1); cur_pixel_pos.y += y_grid_size; colors[4] = recursive_ray_trace(cur_pixel_pos, ray, 1); ret_color = {0,0,0}; for (int i = 0; i < 5; ++i) { ret_color += colors[i]; } ret_color /= 5; } else { ret_color = colors[0]; } frame_mutex.lock(); frame[i][j][0] = ret_color.r; frame[i][j][1] = ret_color.g; frame[i][j][2] = ret_color.b; frame_mutex.unlock(); }
RGB_float recursive_ray_trace(Vector ray, Point p, int step) { RGB_float color = background_clr; RGB_float reflected_color = {0,0,0}; RGB_float refracted_color = {0,0,0}; Spheres *closest_sph; Point *hit = new Point; closest_sph = intersect_scene(p, ray, scene, hit); //get the point color here //intersects a sphere Point *plane_hit = new Point; color = background_clr; if(chessboard_on && intersect_plane(p, ray, N_plane, p0, plane_hit)) { Vector eye_vec = get_vec(*plane_hit, eye_pos); Vector light_vec = get_vec(*plane_hit, p); normalize(&light_vec); normalize(&eye_vec); color = colorPlane(*plane_hit); Vector shadow_vec = get_vec(*plane_hit, light1); Spheres *sph = NULL; if(inShadow(*plane_hit, shadow_vec, scene, sph) && shadow_on) { color = clr_scale(color, .5); } } if(closest_sph != NULL) { Vector eye_vec = get_vec(*hit, eye_pos); Vector surf_norm = sphere_normal(*hit, closest_sph); Vector light_vec = get_vec(*hit, p); normalize(&light_vec); normalize(&surf_norm); normalize(&eye_vec); color = phong(*hit, eye_vec, surf_norm, closest_sph); if(step < step_max && reflection_on) { Vector reflect_vec = vec_minus(vec_scale(surf_norm, vec_dot(surf_norm, light_vec)*2), light_vec); step += 1; normalize(&reflect_vec); reflected_color = recursive_ray_trace(reflect_vec, *hit, step); reflected_color = clr_scale(reflected_color, closest_sph->reflectance); color = clr_add(color, reflected_color); } if(step < step_max && refraction_on) { Vector refracted_ray = getRefractedRay(1.51, closest_sph, surf_norm, light_vec); step += 1; normalize(&refracted_ray); refracted_ray.x = hit->x + refracted_ray.x; refracted_ray.y = hit->x + refracted_ray.y; refracted_ray.z = hit->x + refracted_ray.z; refracted_color = recursive_ray_trace(refracted_ray, *hit, step); color = clr_add(color, reflected_color); } return color; } else { return color; } }
/********************************************************************* * This function traverses all the pixels and cast rays. It calls the * recursive ray tracer and assign return color to frame *********************************************************************/ void ray_trace() { int i, j; float x_grid_size = image_width / float(win_width); float y_grid_size = image_height / float(win_height); float x_start = -0.5 * image_width; float y_start = -0.5 * image_height; glm::vec3 ret_color; glm::vec3 cur_pixel_pos; // ray is cast through center of pixel cur_pixel_pos.x = x_start + 0.5 * x_grid_size; cur_pixel_pos.y = y_start + 0.5 * y_grid_size; cur_pixel_pos.z = image_plane; float antiAlias[5][2] = { {-0.25, +0.25}, {+0.25, +0.25}, {0,0}, {-0.25, -0.25}, {+0.25, -0.25} }; srand(time(NULL)); for (i=0; i<win_height; i++) { for (j=0; j<win_width; j++) { ret_color = glm::vec3(0,0,0); if(antiAlias_on){ for(int k=0;k<5;k++){ glm::vec3 pixel_pos = cur_pixel_pos + glm::vec3(antiAlias[k][0] * x_grid_size,antiAlias[k][1] * y_grid_size,0); glm::vec3 ray = glm::normalize(pixel_pos - eye_pos); ret_color += recursive_ray_trace(eye_pos,ray,0,0); } ret_color /= 5; } else{ //ray = get_vec(eye_pos, cur_pixel_pos); glm::vec3 ray = cur_pixel_pos - eye_pos; //normalize(&ray); ray = glm::normalize(ray); // // You need to change this!!! // ret_color = recursive_ray_trace(eye_pos,ray,0,0); //else ret_color = background_clr; // just background for now // Parallel rays can be cast instead using below // // ray.x = ray.y = 0; // ray.z = -1.0; // ret_color = recursive_ray_trace(cur_pixel_pos, ray, 1); // Checkboard for testing // glm::vec3 clr = glm::vec3(float(i/32), 0, float(j/32)); //ret_color = clr; } frame[i][j] = ret_color; cur_pixel_pos.x += x_grid_size; } cur_pixel_pos.y += y_grid_size; cur_pixel_pos.x = x_start; } }
/************************************************************************ * This is the recursive ray tracer ************************************************************************/ glm::vec3 recursive_ray_trace(glm::vec3 eye, glm::vec3 ray,int ignore, int step) { Object* S = NULL; glm::vec3 hit; S = intersectScene(eye, ray, &hit, ignore); //printf("%d : after intersect scene (type: '%c')\n", step, S==NULL?'N':S->type); glm::vec3 color; if(S == NULL) color = background_clr; else { //color = glm::vec3(1.0,1.0,1.0); glm::vec3 viewDir = glm::normalize(eye - hit); glm::vec3 surf_norm = S->GetNormal(hit); //printf(" after get normal\n"); color = phong(hit,viewDir, surf_norm, S ); //printf(" after phong\n"); if(reflect_on && step < step_max){ //printf(" enter reflect\n"); glm::vec3 reflectDir = glm::normalize(glm::rotate(viewDir, glm::radians(180.0f), surf_norm)); glm::vec3 color_rf = recursive_ray_trace(hit, reflectDir, S->index, step+1); color += color_rf * S->reflectance ; //printf(" exit reflect\n"); } if(refract_on && step < step_max && S->refract ){ if(S->type == 'S'){ glm::vec3 outRay, outPoint; if(S->Refract(ray, hit, &outRay, &outPoint)){ glm::vec3 color_rfr = recursive_ray_trace(outPoint, outRay, S->index, step+2); color += color_rfr * S->refractance; } } else{ glm::vec3 outRay; if(S->GetRefractRay(ray, hit, &outRay)){ glm::vec3 color_rfr = recursive_ray_trace(hit,outRay, S->index, step+1); color += color_rfr * S->refractance; } } } if(difref_on && step < 2){ for(int i=0;i<DIFFUSE_RAYS;i++){ glm::vec3 difrefDir = glm::normalize(glm::rotate(viewDir, glm::radians(180.0f), surf_norm)); glm::vec3 axis = glm::cross(viewDir, surf_norm); float angle1 = random(-5.0f,0.0f); difrefDir = glm::rotate(difrefDir, glm::radians(angle1), axis); float angle2 = random(-5.0f,5.0f); difrefDir = glm::rotate(difrefDir, glm::radians(angle2), surf_norm); difrefDir = glm::normalize(difrefDir); glm::vec3 color_difref = recursive_ray_trace(hit, difrefDir, S->index, step+1); color += color_difref * float(0.1); } } } return color; }
/********************************************************************* * This function traverses all the pixels and cast rays. It calls the * recursive ray tracer and assign return color to frame * * You should not need to change it except for the call to the recursive * ray tracer. Feel free to change other parts of the function however, * if you must. *********************************************************************/ void ray_trace() { printf("entering the ray tracer\n"); int i, j; float x_grid_size = image_width / float(win_width); float y_grid_size = image_height / float(win_height); float x_start = -0.5 * image_width; float y_start = -0.5 * image_height; vec3 ret_color; vec3 cur_pixel_pos; vec3 ray; // ray is cast through center of pixel cur_pixel_pos.x = x_start + 0.5 * x_grid_size; cur_pixel_pos.y = y_start + 0.5 * y_grid_size; cur_pixel_pos.z = image_plane; //printf("window height:%d\n",win_height); //printf("window width:%d\n",win_width); //printf("%d\n",WIN_HEIGHT); //printf("%d\n",WIN_WIDTH); for (i=0; i<win_height; i++) { for (j=0; j<win_width; j++) { //printf("cur_pixel_pos:%f %f %f\n",cur_pixel_pos.x, cur_pixel_pos.y, cur_pixel_pos.z); ret_color = vec3(0,0,0); ray = cur_pixel_pos - eye_pos; ray = normalize(ray); // // You need to change this!!! // ret_color += recursive_ray_trace(eye_pos, ray, 0, false); if(antialias_on) { vec3 pixel; pixel.z = cur_pixel_pos.z; // pixel 1 pixel.x = cur_pixel_pos.x - 0.25*x_grid_size; pixel.y = cur_pixel_pos.y + 0.25*y_grid_size; ray = normalize(pixel - eye_pos); ret_color += recursive_ray_trace(eye_pos, ray, 0, false); // pixel 2 pixel.x = cur_pixel_pos.x - 0.25*x_grid_size; pixel.y = cur_pixel_pos.y - 0.25*y_grid_size; ray = normalize(pixel - eye_pos); ret_color += recursive_ray_trace(eye_pos, ray, 0, false); // pixel 3 pixel.x = cur_pixel_pos.x + 0.25*x_grid_size; pixel.y = cur_pixel_pos.y + 0.25*y_grid_size; ray = normalize(pixel - eye_pos); ret_color += recursive_ray_trace(eye_pos, ray, 0, false); // pixel 4 pixel.x = cur_pixel_pos.x + 0.25*x_grid_size; pixel.y = cur_pixel_pos.y - 0.25*y_grid_size; ray = normalize(pixel - eye_pos); ret_color += recursive_ray_trace(eye_pos, ray, 0, false); ret_color = 0.2*ret_color; } frame[i][j][0] = GLfloat(ret_color.x); frame[i][j][1] = GLfloat(ret_color.y); frame[i][j][2] = GLfloat(ret_color.z); cur_pixel_pos.x += x_grid_size; } cur_pixel_pos.y += y_grid_size; cur_pixel_pos.x = x_start; } }
/************************************************************************ * This is the recursive ray tracer - you need to implement this! * You should decide what arguments to use. ************************************************************************/ vec3 recursive_ray_trace(vec3 eye, vec3 ray, int num, bool inobj) { // // do your thing here // if(num>step_max) return null_clr; vec3 hit; int isplane; void *sph = intersect_scene(eye, ray, scene, &hit, &isplane); vec3 color = null_clr; if(sph==NULL) { return background_clr; } vec3 lightvec = light1 - hit; vec3 lightvec_normal = normalize(lightvec); vec3 lighthit; int lightisplane; void * light_sph = intersect_scene(hit, lightvec_normal, scene, &lighthit, &lightisplane); vec3 surf_normal = isplane?vec3(0,1,0):sphere_normal(hit, (Spheres*)sph); if(light_sph==NULL) { color += phong(-1*ray, lightvec, surf_normal, sph, hit, isplane); } else { if(!shadow_on) { color += phong(-1*ray, lightvec, surf_normal, sph, hit, isplane); } else { color += get_shadow(-1*ray, lightvec, surf_normal, sph, hit, isplane); } } if(reflect_on) { vec3 reflect_vector = 2*dot(-1*ray, surf_normal)*surf_normal + ray; reflect_vector = normalize(reflect_vector); if(isplane) { color += ((struct plane*)sph)->reflectance * recursive_ray_trace(hit, reflect_vector,num+1, inobj); } else if(!isplane) color += ((Spheres *)sph)->reflectance * recursive_ray_trace(hit, reflect_vector, num+1, inobj); } if(refract_on) { vec3 outlightvector; if(refraction(hit, -1*ray, sph, isplane, inobj, &outlightvector)) { if(!isplane) { // printf("refraction point\n"); Spheres * refractsph = (Spheres *)sph; color += refractsph->refr*recursive_ray_trace(hit, outlightvector, num+1, !inobj); } } } if(diffuse_reflection_on && num<2) { int i; for (i=0;i<DIFFUSE_REFLECTION;i++) { float xtheta = 2.0 * static_cast <float> (rand()) / static_cast <float> (RAND_MAX) - 1.0; float ytheta = 2.0 * static_cast <float> (rand()) / static_cast <float> (RAND_MAX) - 1.0; float ztheta = 2.0 * static_cast <float> (rand()) / static_cast <float> (RAND_MAX) - 1.0; vec3 dfray; dfray = rotateX(xtheta*M_PI,surf_normal); dfray = rotateY(ytheta*M_PI,dfray); dfray = rotateZ(ztheta*M_PI,dfray); color += (0.1/DIFFUSE_REFLECTION)*recursive_ray_trace(hit, dfray, num+1, inobj); } } return color; }
/********************************************************************* * Phong illumination ray *********************************************************************/ vec3 phong(vec3 hit, vec3 viewDir, vec3 surf_norm, vec3 ray, Object *obj, int step) { // globle ambient vec3 mat_ambient = obj->GetAmbient(hit); vec3 ambient = light1_ambient * mat_ambient ; // decay float dist = glm::length(light1 - hit); float decay = 1 / ( decay_a + decay_b * dist + decay_c * dist * dist ); // diffuse vec3 lightDir = glm::normalize(light1 - hit); surf_norm = glm::normalize(surf_norm); vec3 mat_diffuse = obj->GetDiffuse(hit); vec3 diffuse = decay * (light1_diffuse * mat_diffuse ) * max(glm::dot(surf_norm, lightDir),0) ; // specular vec3 reflectDir = 2 * glm::dot(surf_norm,lightDir) * surf_norm - lightDir ; reflectDir = glm::normalize(reflectDir); viewDir = glm::normalize(viewDir); float reflectTerm = max(glm::dot(reflectDir, viewDir),0); vec3 specular = decay * ( light1_specular * obj->mat_specular) * (float) pow( reflectTerm, obj->mat_shineness) ; //shadow test vec3 temp; bool shadow = false; if( shadow_on && intersectScene(hit, lightDir, &temp, obj->index) != NULL ) shadow = true; // calc color vec3 color = global_ambient * mat_ambient + ambient; if(!shadow) color += diffuse + specular; //specular reflect ray if(reflect_on && step < step_max){ vec3 reflectDir = glm::normalize(glm::rotate(viewDir, glm::radians(180.0f), surf_norm)); vec3 color_rf = recursive_ray_trace(hit, reflectDir, obj->index, step+1); color += color_rf * obj->reflectance ; } //diffuse reflect ray if(difref_on && step < 2){ for(int i=0;i < DIFFUSE_RAYS;i++){ vec3 difrefDir = glm::normalize(glm::rotate(viewDir, glm::radians(180.0f), surf_norm)); vec3 axis = glm::cross(viewDir, surf_norm); float angle1 = random(-5.0f,0.0f); difrefDir = glm::rotate(difrefDir, glm::radians(angle1), axis); float angle2 = random(-5.0f,5.0f); difrefDir = glm::rotate(difrefDir, glm::radians(angle2), surf_norm); difrefDir = glm::normalize(difrefDir); vec3 color_difref = recursive_ray_trace(hit, difrefDir, obj->index, step+1); color += color_difref * float(0.5 / DIFFUSE_RAYS); } } if(refract_on && step < step_max && obj->refract ){ vec3 outRay, outPoint; if(obj->Refract(ray, hit, &outRay, &outPoint)){ vec3 color_rfr = recursive_ray_trace(outPoint, outRay, obj->index, step+1); color += color_rfr * obj->refractance; } } return color; }