int main(int argc, char** argv) { const size_t kWidth = 1000; const size_t kHeight = 1000; fprintf(stderr, "Rendering %zu frames\n", kFramesToRender); unsigned char* buffer = calloc(4, kWidth * kHeight); struct timeval start; gettimeofday(&start, NULL); for (size_t i = 0; i < kFramesToRender; ++i) trace_scene(i * 0.01f, kWidth, kHeight, buffer, 1); struct timeval end; gettimeofday(&end, NULL); free(buffer); fprintf(stderr, "Average %.2f ms/frame\n", (1.0e3 * (end.tv_sec - start.tv_sec) + 1.0e-3 * (end.tv_usec - start.tv_usec)) / kFramesToRender); return EXIT_SUCCESS; }
//recursive function void World::trace_scene(Scene_info &info, Directional_ray &ray, Directional_ray &spec_light, int rec_ctr, int cur_obj_idx, float min_distance, int i, int j, Vector3d &amb_dir, float factor, Point3d &cur_orig) { if(rec_ctr <= 0) return; for (int o = 0; o < _objects.size(); ++o){ if((o != cur_obj_idx)){//dont hit yourself again if( _tracer->hit(ray, _objects[o], info) ){ //get the color //lambertian shading //calculate the cos value if(_objects[o]->type() == obj_type::Triangle){ Triangle* cur_tri = reinterpret_cast<Triangle*>(_objects[o]); Vector3d tri_normal = cur_tri->get_n(); update_color(info, i, j, tri_normal, amb_dir, 1.f); } else if(_objects[o]->type() == obj_type::Sphere){//sphere Sphere* cur_sph = reinterpret_cast<Sphere*>(_objects[o]); Vector3d normal_hit = info._hit_point - cur_sph->center(); normal_hit.normalize_vector(); if(rec_ctr == MAX_RECURSE_NUM)//first time update_color(info, i, j, normal_hit, amb_dir, 1.f); else//average color update_color(info, i, j, normal_hit, amb_dir, factor); Directional_ray new_ray(ray); Scene_info new_info(info); update_dir_and_org(new_info, new_ray, normal_hit); trace_scene(new_info, new_ray, spec_light, (rec_ctr-1), o, min_distance, i, j, amb_dir, factor/2, cur_orig); //calaulate spec Vector3d view_vec = info._hit_point - cur_orig; view_vec.normalize_vector(); Directional_ray new_spec(spec_light); update_dir_and_org(new_info, new_spec, normal_hit); Vector3d spec_hit = new_spec.get_dir(); update_spec(info, i, j, spec_hit, view_vec, spec_light); } else { //simply copy the color copy_info_color(info, i, j); } } } } }
int main() { fprintf(stderr, "Rendering %zu frames\n", kFramesToRender); unsigned char *buffer = calloc(4, kWidth * kHeight); for (size_t i = 0; i < kFramesToRender; ++i) { trace_scene(i * 0.1f, kWidth, kHeight, buffer, 1); save_ppm(buffer, kWidth, kHeight, "out_%06u.ppm", i); fprintf(stderr, " %zu\n", i); } return EXIT_SUCCESS; }
void World::render_world() { //set all pixels: alpha to 255, color to 0 for (int l = 0; l < vp.width()*vp.height()*4; ++l){ if((l+1)%4 == 0)//alpha _pixels[l] = 255; else _pixels[l] = 0; } //setup ambient light Directional_ray amb_ray;//used for shading Vector3d amb_dir = Vector3d(1.f,1.f,0.f); amb_dir.normalize_vector(); amb_ray.set_direction(amb_dir); //the tracing ray Directional_ray ray; Directional_ray spec_light; //The place to hold pixel data Scene_info info; //start point of ray Point3d cur_orig; float x_off = vp.ref_point().get_x(); float y_off = vp.ref_point().get_y(); float z_off = vp.ref_point().get_z(); float ax_step = vp.A().get_x(); float bx_step = vp.B().get_x(); float ay_step = vp.A().get_y(); float by_step = vp.B().get_y(); float az_step = vp.A().get_z(); float bz_step = vp.B().get_z(); float zw = 100.0; // hard-coded vp.set_pixel_size(2.0); Vector3d dir(0.f,0.f,-1.f); ray.set_direction(dir); //setup environment light Vector3d environment_dir(3.f,4.f,-5.f); environment_dir.normalize_vector(); spec_light.set_direction(environment_dir); std::cout<<"Start ray tracing"<<std::endl; std::cout<<_objects.size()<<" objects involve(s)."<<std::endl; //build the pixel buffer int red_sum = 0; int green_sum = 0; int blue_sum = 0; int rec_ctr = MAX_RECURSE_NUM; float factor = TRACE_FACTOR; srand (time(NULL)); for (int i = 0; i < vp.height(); ++i) { std::cout<<"Processing line "<<i<<std::endl; for (int j = 0; j < vp.width(); ++j) { red_sum = 0; green_sum = 0; blue_sum = 0; //reset pixel color _pixels[i*vp.width()*4 + j*4 + 0] = 0; _pixels[i*vp.width()*4 + j*4 + 1] = 0; _pixels[i*vp.width()*4 + j*4 + 2] = 0; for (int sample_count = 0; sample_count<SAMPLE_PER_PIXEL; ++sample_count){ //rand sample point float yr = (rand() % (int)(vp.pixel_size()*100) )*0.01; float xr = (rand() % (int)(vp.pixel_size()*100) )*0.01; float zr = (rand() % (int)(vp.pixel_size()*100) )*0.01; //reset path tracer factor = TRACE_FACTOR; rec_ctr = MAX_RECURSE_NUM; //TODO: dont forget to change this back if( !PERSPECTIVE ){ cur_orig.set_point(y_off + vp.pixel_size() * (i - vp.height() / 2.0 + 0.5) * ay_step + vp.pixel_size() * (j - vp.width() / 2.0 + 0.5) * by_step+yr, x_off + vp.pixel_size() * (i - vp.height() / 2.0 + 0.5) * ax_step + vp.pixel_size() * (j - vp.width() / 2.0 + 0.5) * bx_step+xr, z_off + vp.pixel_size() * (i - vp.height() / 2.0 + 0.5) * az_step + vp.pixel_size() * (j - vp.width() / 2.0 + 0.5) * bz_step+zr); } else{ ray.set_destination(Point3d(0.f,0.f,-10800.f)); Vector3d dir = ray.get_dest() - cur_orig; dir.normalize_vector(); ray.set_direction(dir); cur_orig.set_point(y_off+vp.pixel_size() * (j - vp.width() / 2.0 + 0.5)+yr, x_off+vp.pixel_size() * (i - vp.height() / 2.0 + 0.5)+xr, z_off+zw+zr); } //set the origin and dir of the tracing ray ray.set_origin(cur_orig); ray.set_direction(dir); //"z-buffer" float min_distance = 3.4e38;//set as the max value of float int cur_obj_idx = -1; trace_scene(info, ray, spec_light, rec_ctr, cur_obj_idx, min_distance, i, j, amb_dir, factor, cur_orig); red_sum += _pixels[i*vp.width()*4 + j*4 + 0]; green_sum += _pixels[i*vp.width()*4 + j*4 + 1]; blue_sum += _pixels[i*vp.width()*4 + j*4 + 2]; } //calculate final color if(SAMPLE_PER_PIXEL != 0){ _pixels[i*vp.width()*4 + j*4 + 0] = red_sum/SAMPLE_PER_PIXEL; _pixels[i*vp.width()*4 + j*4 + 1] = green_sum/SAMPLE_PER_PIXEL; _pixels[i*vp.width()*4 + j*4 + 2] = blue_sum/SAMPLE_PER_PIXEL; } } } std::cout<<"Ray tracing finished!"<<std::endl; }