vector<vec3f> PhotonMap::renderPixels(const Camera& camera){ uint width = camera.width, height = camera.height; std::vector<vec3f> pixelColors(width * height, vec3f(0,0,0)); omp_init_lock(&surfaceHashGridLock); omp_init_lock(&volumeHashGridLock); omp_init_lock(&debugPrintLock); //std::vector<int> pixelMaps(pixelColors.size(), 0); preprocessEmissionSampler(); mRadius = mBaseRadius; clock_t startTime = clock(); for(uint s = 0; s < spp; s++){ std::cout << "iteration : " << s << std::endl; std::vector<vec3f> oneIterColors(pixelColors.size(), vec3f(0,0,0)); #ifdef PPM //if (renderer->scene.getTotalVolume() > 1e-6f) if (true) { rayMarching = true; mRadius = MAX(mBaseRadius * powf(powf(s+1 , mAlpha-1) , 1.f / 3.f) , EPSILON); } else { rayMarching = false; mRadius = MAX(mBaseRadius * sqrt(powf(s+1, mAlpha-1)), EPSILON); } #endif std::vector<Path*> pixelLightPaths(mPhotonsNum, NULL); std::vector<LightPoint> surfaceLightVertices(0); std::vector<LightPoint> volumeLightVertices(0); surfaceHashGrid.Reserve(pixelColors.size()); volumeHashGrid.Reserve(pixelColors.size()); #pragma omp parallel for // step1: sample light paths and build range search struct independently for surface and volume for(int p = 0; p < mPhotonsNum; p++){ Ray lightRay = genEmissiveSurfaceSample(true , false); pixelLightPaths[p] = new Path; Path &lightPath = *pixelLightPaths[p]; samplePath(lightPath, lightRay); for(int i = 1; i < lightPath.size(); i++){ // light is not reflective if(lightPath[i].contactObject && lightPath[i].contactObject->emissive()) break; // only store particles non-specular if(lightPath[i].directionSampleType == Ray::DEFINITE) continue; LightPoint lightPoint; lightPoint.position = lightPath[i].origin; lightPoint.indexInThePath = i; lightPoint.pathThePointIn = &lightPath; lightPoint.photonType = lightPath[i].photonType; if(lightPoint.photonType == Ray::OUTVOL){ omp_set_lock(&surfaceHashGridLock); surfaceLightVertices.push_back(lightPoint); omp_unset_lock(&surfaceHashGridLock); } if(lightPoint.photonType == Ray::INVOL){ omp_set_lock(&volumeHashGridLock); volumeLightVertices.push_back(lightPoint); omp_unset_lock(&volumeHashGridLock); } } } std::cout<< "vol vertices= " << volumeLightVertices.size() << " sur vertices= " << surfaceLightVertices.size() << std::endl; surfaceHashGrid.Build(surfaceLightVertices, mRadius); volumeHashGrid.Build(volumeLightVertices, mRadius); std::cout<< "finish building hashgrid" << std::endl; // step2: calculate pixel colors by progressive photon mapping #pragma omp parallel for for(int p = 0; p < pixelColors.size(); p++){ Path eyePath; if (rayMarching) sampleMergePath(eyePath, camera.generateRay(p), 0); else samplePath(eyePath, camera.generateRay(p)); //fprintf(fp , "===================\n"); //for (int i = 0; i < eyePath.size(); i++) //{ // fprintf(fp , "l=%d, bsdf=(%.8f,%.8f,%.8f), originPdf=%.8f, dirPdf=%.8f\n" , i , eyePath[i].color.x , // eyePath[i].color.y , eyePath[i].color.z , eyePath[i].originProb , eyePath[i].directionProb); //} /*if(eyePath[1].contactObj && eyePath[1].contactObj->anisotropic()){ pixelMaps[p] = 1; }*/ throughputByDensityEstimation(oneIterColors[p], eyePath, surfaceLightVertices, volumeLightVertices); } /*std::ofstream fout(engine->renderer->name + engine->scene.name+"pixelMap.txt"); for(int p = 0; p < pixelMaps.size(); p++) fout << pixelMaps[p] << ' ' ; fout << std::endl; fout.close();*/ std::cout << "calculation done" << std::endl; for(uint i = 0; i < pixelColors.size(); i++){ pixelColors[i] *= s / float(s+1); pixelColors[i] += camera.eliminateVignetting(oneIterColors[i], i) / (s + 1); delete pixelLightPaths[i]; } unsigned nowTime = (float)(clock() - startTime) / 1000; //if (nowTime > recordTime) if (s % outputIter == 0) { showCurrentResult(pixelColors , &nowTime , &s); //showCurrentResult(pixelColors , &lastTime , &s); //recordTime += timeInterval; } else showCurrentResult(pixelColors); } return pixelColors; }
void IptTracer::genIntermediatePaths(omp_lock_t& cmdLock , vector<Path*>& interPathList) { #pragma omp parallel for for(int p=0; p<interPathNum; p++) { if (!renderer->scene.usingGPU()) { Ray interRay = genIntermediateSamples(renderer->scene); interPathList[p] = new Path; samplePath(*interPathList[p] , interRay); } Path& interPath = *interPathList[p]; //fprintf(fp , "=================\n"); partPathMergeIndex[p].clear(); if (interPath.size() <= 1) continue; IptPathState interState; interState.originRay = &interPath[0]; interState.throughput = interPath[0].color * interPath[0].getCosineTerm() / (interPath[0].originProb * interPath[0].directionProb * interPath[1].originProb); interState.indirContrib = vec3f(0.f); interState.mergedPath = 0; //if (intensity(interState.throughput) > 30.f) // continue; /* fprintf(fp , "====================\n"); vec3f decay = interPath[0].getRadianceDecay((interPath[0].origin - interPath[1].origin).length()); fprintf(fp , "l = 0 , thr = (%.8f,%.8f,%.8f) , color = (%.8f,%.8f,%.8f)\ncosine = %.8f , dirPdf = %.8f , oPdf = %.8f\ndecay=(%.8f,%.8f,%.8f)\n" , interState.throughput.x , interState.throughput.y , interState.throughput.z , interPath[0].color[0] , interPath[0].color[1] , interPath[0].color[2] , interPath[0].getCosineTerm() , interPath[0].directionProb , interPath[1].originProb , decay.x , decay.y , decay.z); */ for(unsigned i = 1; i < interPath.size(); i++) //for (unsigned i = 1; i < 2; i++) { Real dist = std::max((interPath[i].origin - interPath[i - 1].origin).length() , 1e-5f); interState.throughput *= interPath[i - 1].getRadianceDecay(dist); if(interPath[i].contactObject && interPath[i].contactObject->emissive()) break; interState.pos = interPath[i].origin; interState.lastRay = &interPath[i - 1]; interState.ray = &interPath[i]; interState.pathLen = i; if(interPath[i].directionSampleType != Ray::DEFINITE && (interPath[i].insideObject != NULL || interPath[i].contactObject != NULL) && (interPath[i].origin != interPath[i - 1].origin)) //(interPath[i].insideObject && !interPath[i].contactObject)) // only volume { //fprintf(fp , "path length = %d, dirContrib = (%.8f,%.8f,%.8f)\n" , // i , interState.dirContrib[0] , interState.dirContrib[1] , interState.dirContrib[2]); omp_set_lock(&cmdLock); partialSubPathList.push_back(interState); partPathMergeIndex[p].push_back(partialSubPathList.size() - 1); omp_unset_lock(&cmdLock); } if (i == interPath.size() - 1) break; if (interPath[i].direction.length() < 0.5f) break; vec3f scatterFactor = (interPath[i].color * interPath[i].getCosineTerm() / (interPath[i + 1].originProb * interPath[i].directionProb)); interState.throughput *= scatterFactor; /* vec3f decay = interPath[i].getRadianceDecay((interPath[i].origin - interPath[i + 1].origin).length()); fprintf(fp , "l = %d , thr = (%.8f,%.8f,%.8f) , color = (%.8f,%.8f,%.8f)\ncosine = %.8f , dirPdf = %.8f , oPdf = %.8f\ndecay=(%.8f,%.8f,%.8f)\n" , i , interState.throughput.x , interState.throughput.y , interState.throughput.z , interPath[i].color[0] , interPath[i].color[1] , interPath[i].color[2] , interPath[i].getCosineTerm() , interPath[i].directionProb , interPath[i + 1].originProb , decay.x , decay.y , decay.z); */ if (interPath[i].directionSampleType != Ray::DEFINITE && useWeight) { Real pdf = interPath[i].directionProb; if (pdf < 1e-7f) break; Real weightFactor; Real volMergeScale = 1.f; Real originProb; Real dirProb; if (interPath[i].contactObject) { if (useUniformSur) originProb = 1.f / totArea; else originProb = interPath[i].contactObject->getOriginProb(interPath[i].contactObjectTriangleID); if (useUniformDir) dirProb = INV_2_PI; else dirProb = interPath[i].getCosineTerm() / M_PI; } //if (interPath[i].insideObject && interPath[i].contactObject) // printf("!!!\n"); if (interPath[i].insideObject && !interPath[i].contactObject && interPath[i].insideObject->isVolumetric()) { volMergeScale = 4.f / 3.f * mergeRadius; if (useUniformVol) originProb = 1.f / totVol; else originProb = interPath[i].insideObject->getOriginProb(interPath[i].origin); dirProb = 0.25f / M_PI; } weightFactor = connectFactor(pdf) / (connectFactor(pdf) + mergeFactor(&volMergeScale , &originProb , &dirProb , &partialPathNum)); if (_isnan(weightFactor) || abs(pdf) < 1e-6f) { fprintf(err , "sample inter path error, %.8f , %.8f\n" , connectFactor(pdf) , mergeFactor(&volMergeScale , &originProb , &dirProb , &partialPathNum)); } //if (interPath[i].contactObject && interPath[i].contactObject->objectIndex == 7) interState.throughput *= weightFactor; } } } partialPhotonNum = partialSubPathList.size(); }
void IptTracer::genLightPaths(omp_lock_t& cmdLock , vector<Path*>& lightPathList , bool isFirstIter) { #pragma omp parallel for for(int p=0; p<lightPathNum; p++) { if (!renderer->scene.usingGPU()) { Ray lightRay = genEmissiveSurfaceSample(true , false); lightPathList[p] = new Path; samplePath(*lightPathList[p] , lightRay); } Path& lightPath = *lightPathList[p]; if (lightPath.size() <= 1) continue; IptPathState lightState; lightState.originRay = &lightPath[0]; Real cosAtLight = lightPath[0].getCosineTerm(); lightState.throughput = lightPath[0].color * cosAtLight / (lightPath[0].originProb * lightPath[0].directionProb * lightPath[1].originProb); lightState.indirContrib = vec3f(0.0); lightState.mergedPath = 1; /* fprintf(fp , "====================\n"); vec3f decay = lightPath[0].getRadianceDecay((lightPath[0].origin - lightPath[1].origin).length()); fprintf(fp , "l = 0 , thr = (%.8f,%.8f,%.8f) , color = (%.8f,%.8f,%.8f)\ncosine = %.8f , dirPdf = %.8f , oPdf = %.8f\ndecay=(%.8f,%.8f,%.8f)\n" , lightState.throughput.x , lightState.throughput.y , lightState.throughput.z , lightPath[0].color[0] , lightPath[0].color[1] , lightPath[0].color[2] , lightPath[0].getCosineTerm() , lightPath[0].directionProb , lightPath[1].originProb , decay.x , decay.y , decay.z); */ int nonSpecPathLength = 0; for(unsigned i = 1; i < lightPath.size(); i++) //for (unsigned i = 1; i < 2; i++) { Real dist = std::max((lightPath[i].origin - lightPath[i - 1].origin).length() , 1e-5f); vec3f decayFactor = lightPath[i - 1].getRadianceDecay(dist); lightState.throughput *= decayFactor; if(lightPath[i].contactObject && lightPath[i].contactObject->emissive()) break; lightState.pos = lightPath[i].origin; lightState.lastRay = &lightPath[i - 1]; lightState.ray = &lightPath[i]; lightState.pathLen = i; if(lightPath[i].directionSampleType == Ray::RANDOM && (lightPath[i].insideObject != NULL || lightPath[i].contactObject != NULL) && (lightPath[i].origin != lightPath[i - 1].origin)) { //if (lightPath[i].insideObject && !lightPath[i].contactObject) // fprintf(fp , "path length = %d, dirContrib = (%.8f,%.8f,%.8f)\n" , // i , lightState.dirContrib[0] , lightState.dirContrib[1] , lightState.dirContrib[2]); omp_set_lock(&cmdLock); partialSubPathList.push_back(lightState); omp_unset_lock(&cmdLock); } if (i == lightPath.size() - 1) break; if (lightPath[i].direction.length() < 0.5f) break; vec3f scatterFactor = (lightPath[i].color * lightPath[i].getCosineTerm() / (lightPath[i + 1].originProb * lightPath[i].directionProb)); lightState.throughput *= scatterFactor; /* vec3f decay = lightPath[i].getRadianceDecay((lightPath[i].origin - lightPath[i + 1].origin).length()); fprintf(fp , "l = %d , thr = (%.8f,%.8f,%.8f) , color = (%.8f,%.8f,%.8f)\ncosine = %.8f , dirPdf = %.8f , oPdf = %.8f\ndecay=(%.8f,%.8f,%.8f)\n" , i , lightState.throughput.x , lightState.throughput.y , lightState.throughput.z , lightPath[i].color[0] , lightPath[i].color[1] , lightPath[i].color[2] , lightPath[i].getCosineTerm() , lightPath[i].directionProb , lightPath[i + 1].originProb , decay.x , decay.y , decay.z); */ if (lightPath[i].directionSampleType == Ray::RANDOM && useWeight) { Real pdf = lightPath[i].directionProb; if (pdf < 1e-7f) break; Real weightFactor; Real volMergeScale = 1; Real originProb; Real dirProb; if (lightPath[i].contactObject) { if (isFirstIter || useUniformSur) originProb = 1.f / totArea; else originProb = lightPath[i].contactObject->getOriginProb(lightPath[i].contactObjectTriangleID); if (useUniformDir) dirProb = INV_2_PI; else dirProb = lightPath[i].getCosineTerm() / M_PI; } //if (lightPath[i].insideObject && lightPath[i].contactObject) // printf("!!!\n"); if (lightPath[i].insideObject && !lightPath[i].contactObject && lightPath[i].insideObject->isVolumetric()) { volMergeScale = 4.f / 3.f * mergeRadius; if (isFirstIter || useUniformVol) originProb = 1.f / totVol; else originProb = lightPath[i].insideObject->getOriginProb(lightPath[i].origin); dirProb = 0.25f / M_PI; } weightFactor = connectFactor(pdf) / (connectFactor(pdf) + mergeFactor(&volMergeScale , &originProb , &dirProb , &lightPathNum)); if (_isnan(weightFactor) || abs(pdf) < 1e-6f) { fprintf(err , "sample light path error, %.8f , %.8f\n" , connectFactor(pdf) , mergeFactor(&volMergeScale , &originProb , &dirProb , &lightPathNum)); } /* if (abs(volMergeScale - 1.f) < 1e-6) printf("surface %.8f\n" , weightFactor); else printf("volume %.8f %.8f\n" , weightFactor); */ //if (lightPath[i].contactObject && lightPath[i].contactObject->objectIndex == 7) lightState.throughput *= weightFactor; } } } lightPhotonNum = partialPhotonNum = partialSubPathList.size(); }
bool transform1(IHypergraph<Arc> const& i, IMutableHypergraph<Arc>* o) { UniformInArcSampler<Arc> sampler; samplePath(i, sampler, o); return true; }
std::vector<vec3f> PathTracer::renderPixels(){ Camera &camera = getCamera(); uint width = camera.mResolution.x, height = camera.mResolution.y; std::vector<vec3f> pixelColors(width * height, vec3f(0,0,0)); if(useNextEventEstimation) prepareForLightSampling(); for(uint s = 0; s < spp; s++){ std::cout << "iteration : " << s << std::endl; engine->scene.updateSceneForMotionBlur(); #pragma omp parallel for for(int p = 0; p < pixelColors.size(); p++){ Path eyePath; samplePath(eyePath, camera.generateRay(p)); pixelColors[p] *= s / float(s+1); vec3f color = vec3f(1,1,1); bool hasToConnect = eyePath[eyePath.size()-1].radiance.length() <= 0; if(!useNextEventEstimation || !hasToConnect){ for(int i = 0; i < eyePath.size(); i++){ if(i != eyePath.size() - 1){ color *= eyePath[i].cosineTerm(); float dist = (eyePath[i+1].origin - eyePath[i].origin).length(); color *= eyePath[i].radianceDecay(dist); } color *= eyePath[i].radiance / eyePath[i].originProb / eyePath[i].directionProb; } } else{ int endIndex = (eyePath.back().contactObj || eyePath.back().insideObj) ? -1 : eyePath.size()-2; if(endIndex <= 0) continue; Ray &endRay = eyePath[endIndex], lightRay = genLightSample(); if(endRay.contactObj && endRay.contactObj->isEmissive()) continue; if(endRay.contactObj && !endRay.contactObj->nonSpecular()) continue; endRay.direction = lightRay.origin - endRay.origin; endRay.direction.normalize(); lightRay.direction = -endRay.direction; float connectDist = MAX((lightRay.origin - endRay.origin).length(), EPSILON); if(endRay.direction.dot(lightRay.contactNormal()) >= 0) continue; if(!visibilityTest(endRay, lightRay)) continue; for(int i = 0; i < endIndex; i++){ color *= eyePath[i].radiance / eyePath[i].originProb / eyePath[i].directionProb; color *= eyePath[i].cosineTerm(); float dist = (eyePath[i+1].origin - eyePath[i].origin).length(); color *= eyePath[i].radianceDecay(dist); } color *= eyePath[endIndex-1].evalBSDF(endRay) * lightRay.radiance * endRay.radianceDecay(connectDist) * lightRay.cosineTerm() * endRay.cosineTerm() / (connectDist * connectDist); color /= eyePath[endIndex].originProb * lightRay.originProb; } if(!isLegalColor(color)) color = vec3f(0,0,0); pixelColors[p] += camera.fixVignetting(color, p) / (s+1); } camera.mFilm.setBuffer(pixelColors); std::string filename = engine->renderer->name + engine->scene.name + ".pfm"; camera.mFilm.savePFM(filename); } return pixelColors; }
vector<vec3f> PathTracer::renderPixels(const Camera& camera) { int t_start = clock(); vector<vec3f> pixelColors(camera.width*camera.height, vec3f(0, 0, 0)); if(useConnection) renderer->scene.preprocessEmissionSampler(); if(!renderer->scene.usingGPU()) { for(unsigned s=0; s<spp; s++) { int t = clock(); #pragma omp parallel for for(int p=0; p<pixelColors.size(); p++) { Path eyePath; samplePath(eyePath, camera.generateRay(p)); pixelColors[p] *= s/float(s+1); if (!(eyePath.back().contactObject && eyePath.back().contactObject->emissive())) continue; vec3f color = vec3f(1, 1, 1); for(unsigned i=0; i<eyePath.size(); i++) { color *= eyePath[i].color / eyePath[i].directionProb / eyePath[i].originProb; if(i!=eyePath.size()-1) { color *= eyePath[i].getCosineTerm(); float dist = (eyePath[i+1].origin - eyePath[i].origin).length(); // NOTE: Must multiply the decay !!!!!!!!! color *= eyePath[i].getRadianceDecay(dist); } } pixelColors[p] += renderer->camera.eliminateVignetting(color, p)/(s+1);//*camera.width*camera.height; //pixelColors[p] += color * eyePath[0].directionProb / (s+1); } //if (clock() / 1000 >= lastTime) if (s % outputIter == 0) { unsigned nowTime = (clock()) / 1000; showCurrentResult(pixelColors , &nowTime , &s); //showCurrentResult(pixelColors , &lastTime , &s); //lastTime += timeInterval; } else showCurrentResult(pixelColors); printf("Iter: %d IterTime: %ds TotalTime: %ds\n", s+1, (clock()-t)/1000, (clock()-t_start)/1000); } } else { for(unsigned s=0; s<spp; s++) { int t = clock(); vector<Ray> eyeRays(pixelColors.size()); #pragma omp parallel for for(int p=0; p<pixelColors.size(); p++) { eyeRays[p] = camera.generateRay(p); } int clk = clock(); vector<Path> pathList = samplePathList(eyeRays); vector<Path> lightPathList; vector<vector<unsigned>> visList; if(useConnection) { lightPathList.resize(pathList.size()); for(unsigned i=0; i<pathList.size(); i++) lightPathList[i].push_back(genEmissiveSurfaceSample(true , false)); visList = testPathListVisibility(pathList, lightPathList); } #pragma omp parallel for for(int p=0; p<pathList.size(); p++) { pixelColors[p] *= s/float(s+1); vec3f color = vec3f(0, 0, 0); //pathList[p][0].directionProb = 1.f; //if(!useConnection || mustUsePT(pathList[p]) || // pathList[p].size()==2 && pathList[p].back().contactObject && pathList[p].back().contactObject->emissive()) if (pathList[p].back().contactObject && pathList[p].back().contactObject->emissive()) { vec3f c(1, 1, 1); for(unsigned i=0; i<pathList[p].size(); i++) { c *= pathList[p][i].color / pathList[p][i].directionProb / pathList[p][i].originProb; if(i!=pathList[p].size()-1) { c *= pathList[p][i].getCosineTerm(); float dist = (pathList[p][i+1].origin - pathList[p][i].origin).length(); // NOTE: Must multiply the decay !!!!!!!!! c *= pathList[p][i].getRadianceDecay(dist); } } color += c; } /* else { Ray &lightRay = lightPathList[p][0]; for(unsigned i=1; i<pathList[p].size(); i++) { if(!((visList[p][i/32]>>(i%32)) & 1)) continue; Path connectedPath; connectedPath.push_back(lightRay); Path &eyePath = pathList[p]; if(eyePath[i].contactObject && eyePath[i].contactObject->emissive()) break; if(eyePath[i].directionSampleType != Ray::RANDOM) continue; for(unsigned k=0; k<=i; k++) connectedPath.push_back(eyePath[i-k]); connectRays(connectedPath, 0); vec4f color_prob = connectColorProb(connectedPath, 0); if(vec3f(color_prob).length()>0 && color_prob.w > 0) color += vec3f(color_prob) / color_prob.w;// / camera.width / camera.height; } } */ pixelColors[p] += renderer->camera.eliminateVignetting(color, p)/(s+1);//*camera.width*camera.height; //pixelColors[p] += color / (s+1); } //if (clock() / 1000 >= lastTime) if (s % outputIter == 0) { unsigned nowTime = (clock()) / 1000; showCurrentResult(pixelColors , &nowTime , &s); //showCurrentResult(pixelColors , &lastTime , &s); //lastTime += timeInterval; } else showCurrentResult(pixelColors); printf("Iter: %d IterTime: %ds TotalTime: %ds\n", s+1, (clock()-t)/1000, (clock()-t_start)/1000); } } return pixelColors; }