/** * @brief Updates the NIKinect's Metda-Data and Image information. * @details When called on multi-threaded environment, use it inside locks. * * @retval true if the information was successfully updated. * @retval false if an error occurred. */ bool NIKinect::update_images(){ //Updates Depth Variables if(this->_flags[NIKinect::DEPTH_G]){ this->_depth_generator->GetMetaData(this->_depth_md); if(this->_flags_processing[NIKinect::DEPTH_P]){ cv::Mat depthMat16UC1(480, 640,CV_16UC1, (void*) this->_depth_md.Data()); depthMat16UC1.copyTo(this->_depth_mat); } if(this->_flags_processing[NIKinect::DEPTH_P]){ //cv::threshold src uses 8-bit or 32-bit floating point so you have to convert before use. Loss of performance. //depthMat16UC1.convertTo(mask8,CV_8UC1); //cv::threshold(mask8,this->_mask_mat,0.1,255,CV_THRESH_BINARY); cv::inRange(this->_depth_mat,1,10000,this->_mask_mat); } if(this->_flags_processing[NIKinect::DEPTH_COLOR]){ double min = this->_min_depth; double max = this->_max_depth; NIKinect::compute_color_encoded_depth(this->_depth_mat,this->_depth_as_color_mat,&min,&max); } } //Updates Image Variables if(this->_flags[NIKinect::IMAGE_G]){ this->_image_generator->GetMetaData(_image_md); if(this->_flags_processing[NIKinect::IMAGE_P]){ cv::Mat color_temp(_image_mode.nYRes,_image_mode.nXRes,CV_8UC3,(void*) _image_md.Data()); cv::cvtColor(color_temp,_color_mat,CV_RGB2BGR); } } if(this->_flags[NIKinect::SCENE_A]){ } if(this->_flags_processing[NIKinect::POINT_CLOUD]){ this->generate_point_cloud(); } this->update_frame_rate(); return true; }
glm::vec3 Integrator::EstimateDirectLighting(const Intersection &isx, unsigned int &samples_taken, const glm::vec3 &woW) { //for Light source sampling //QList<glm::vec3> light_sample_pts; glm::vec3 color_temp(0,0,0); glm::vec3 color_final(0,0,0); Intersection light_sample_isx; //randomly sampled intersection on the light source's surface glm::vec3 wiW; // incoming ray in world frame Ray light_sample_ray; float rand1 = unif_distribution(mersenne_generator); float rand2 = unif_distribution(mersenne_generator); Intersection obstruction_test; //iterate through all the light sources for (int i = 0; i < scene->lights.count(); i++) { for(unsigned int j = 0; j < samples_taken; j++) { light_sample_isx = scene->lights[i]->GetRandISX(rand1, rand2, isx.normal); //take 1 sample point(intersection) on the light source for now wiW = light_sample_isx.point - isx.point; //ray direction going from world point to light source light_sample_isx.t = glm::length(wiW); wiW = glm::normalize(wiW); light_sample_ray = Ray(isx.point, wiW);//remember, the direction is from point in scene to light source obstruction_test = intersection_engine->GetIntersection(light_sample_ray); //update random point rand1 = unif_distribution(mersenne_generator); rand2 = unif_distribution(mersenne_generator); if (obstruction_test.object_hit == scene->lights[i]) { color_temp = color_temp + CalculateEnergy(light_sample_isx, isx, light_sample_ray, woW); } else { //the ray contributes zero energy } } color_temp = color_temp/static_cast<float>(samples_taken); //divide by samples taken color_final = color_final + color_temp; // accumulate energy per high source color_temp = glm::vec3(0, 0, 0);// zero out color_temp for the next light source } return color_final; }
glm::vec3 AllLightingIntegrator::LightIndirectEnergy(const Intersection &isx, unsigned int n_split, const glm::vec3 &woW) { int depth = 0; Intersection isx_temp = isx;//reflected intersection Intersection isx_light; //sampled intersection with "light source" glm::vec3 color_accum(0.0f, 0.0f, 0.0f); //accumulated color glm::vec3 color_temp(0.0f, 0.0f, 0.0f); glm::vec3 wi_temp(0.0f, 0.0f, 0.0f); glm::vec3 wo_temp(woW); glm::vec3 brdf_energy_accum(1.0f, 1.0f, 1.0f); glm::vec3 brdf_energy_temp(0.0f, 0.0f, 0.0f); glm::vec3 L_temp(0.0f, 0.0f, 0.0f); Material* M_temp = isx.object_hit->material; Geometry* obj_temp; //stores the temporary sampled object Ray sampler; float pdf_temp_brdf(0); float pdf_light_temp(0); float W(0); //for MIS float rand1 = unif_distribution(mersenne_generator); float rand2 = unif_distribution(mersenne_generator); float epsilon = 0.0001f; float throughput = 1.000001f; float russian = unif_distribution(mersenne_generator); //default samples for direct lighting when estimating the irradiance of some other point in the scene unsigned int n_light = 10; unsigned int n_brdf = 10; int light_source_choice(0); while(depth < max_depth && (russian < throughput || depth < 2)) { //sample a random point on a random object in the scene light_source_choice = rand()%scene->objects.count(); obj_temp = scene->objects[light_source_choice]; //if I hit a real light source, kill the ray if (scene->objects[light_source_choice]->material->is_light_source) break; isx_light = obj_temp->GetRandISX(rand1, rand2, isx_temp.normal); //update random numbers rand1 = unif_distribution(mersenne_generator); rand2 = unif_distribution(mersenne_generator); //make ray towards these points wi_temp = glm::normalize(isx_light.point - isx_temp.point); sampler = Ray(isx_temp.point, wi_temp); //update my light intersection isx_light = intersection_engine->GetIntersection(sampler); //this ray dies if it hit nothing or is blocked, kill the ray as well if(isx_light.object_hit == NULL) break; if(isx_light.object_hit != obj_temp) break; //to avoid shadow acne isx_light.point = isx_light.point + epsilon*isx_light.normal; //find out the pdf w/r/t light pdf_light_temp = obj_temp->RayPDF(isx_light, sampler); //if my pdf is negative, kill the ray as well if(pdf_light_temp <= 0) break; //update accumulated brdf energy brdf_energy_temp = M_temp->EvaluateScatteredEnergy(isx_temp, wo_temp, wi_temp, pdf_temp_brdf); brdf_energy_accum = ComponentMult(brdf_energy_accum, brdf_energy_temp); //find the direct lighting irradiance of this point towards my original intersection wo_temp = -wi_temp; //now the old incoming ray is the outgoing ray for the new intersection L_temp = EstimateDirectLighting(isx_light, n_light, n_brdf, wo_temp); W = MIS(pdf_light_temp, pdf_temp_brdf); //this is light source sampling so use the illumination equation for BRDF sampling to accumulate color color_temp = ComponentMult(brdf_energy_accum, L_temp); color_temp = ComponentMult(ComponentMult(color_temp, M_temp->base_color), isx_temp.texture_color); color_temp = color_temp*W/pdf_light_temp*glm::abs(glm::dot(isx_temp.normal, wi_temp)); color_accum = color_accum + color_temp/static_cast<float>(n_split); throughput = throughput * glm::max(glm::max(color_accum.r, color_accum.g), color_accum.b); //update the temporary material M_temp = isx_light.object_hit->material; isx_temp = isx_light; //update random number //update depth depth++; russian = unif_distribution(mersenne_generator); } return color_accum; }
glm::vec3 AllLightingIntegrator::BxDFIndirectEnergy(const Intersection &isx, unsigned int n_split, const glm::vec3 &woW) { int depth = 0; Intersection isx_temp = isx;//reflected intersection Intersection isx_light; //sampled intersection with "light source" glm::vec3 color_accum(0.0f, 0.0f, 0.0f); //accumulated color glm::vec3 color_temp(0.0f, 0.0f, 0.0f); glm::vec3 wi_temp(0.0f, 0.0f, 0.0f); glm::vec3 wo_temp(woW); glm::vec3 brdf_energy_accum(1.0f, 1.0f, 1.0f); glm::vec3 brdf_energy_temp(0.0f, 0.0f, 0.0f); glm::vec3 L_temp(0.0f, 0.0f, 0.0f); Material* M_temp = isx.object_hit->material; Ray sampler; float pdf_temp_brdf(0); float pdf_light_temp(0); float W(0); //for MIS float rand1 = unif_distribution(mersenne_generator); float rand2 = unif_distribution(mersenne_generator); float epsilon = 0.0001; float throughput = 1.000001f; float russian = unif_distribution(mersenne_generator); //default samples for direct lighting when estimating the irradiance of some other point in the scene unsigned int n_light = 10; unsigned int n_brdf = 10; while(depth < max_depth && (russian < throughput || depth < 2)) { //sample random brdf starting at the input isx direction to get reflected ray to begin brdf_energy_temp = M_temp->SampleAndEvaluateScatteredEnergy(isx_temp, wo_temp, wi_temp, pdf_temp_brdf, rand1, rand2); //update accumulated brdf energy brdf_energy_accum = ComponentMult(brdf_energy_accum, brdf_energy_temp); //use the sampled incoming ray to find a reflected intersection sampler = Ray(isx_temp.point, wi_temp); isx_light = intersection_engine->GetIntersection(sampler); //this ray dies if I hit a real light source or nothing if(isx_light.object_hit == NULL) break; else if(isx_light.object_hit->material->is_light_source) break; // //to avoid shadow acne isx_light.point = isx_light.point + epsilon*isx_light.normal; //find the direct lighting irradiance of this point towards my original intersection wo_temp = -wi_temp; //now the old incoming ray is the outgoing ray for the new intersection L_temp = EstimateDirectLighting(isx_light, n_light, n_brdf, wo_temp); //the direct lighting towards the isx pdf_light_temp = isx_light.object_hit->RayPDF(isx_light, sampler); W = MIS(pdf_temp_brdf, pdf_light_temp); //this is BRDF sampling so use the illumination equation for BRDF sampling to accumulate color color_temp = ComponentMult(brdf_energy_accum, L_temp); color_temp = ComponentMult(ComponentMult(color_temp, M_temp->base_color), isx_temp.texture_color); color_temp = color_temp*W/pdf_temp_brdf*glm::abs(glm::dot(isx_temp.normal, wi_temp)); color_accum = color_accum + color_temp/static_cast<float>(n_split); throughput = throughput * glm::max(glm::max(color_accum.r, color_accum.g), color_accum.b); //update the temporary material M_temp = isx_light.object_hit->material; isx_temp = isx_light; //update random number rand1 = unif_distribution(mersenne_generator); rand2 = unif_distribution(mersenne_generator); //update depth depth++; russian = unif_distribution(mersenne_generator); } return color_accum; }