/* * pmapimportance.C: Trace importons */ #include "pmapimportance.H" #include "pmapoptions.H" #include "pmapconfig.H" #include "ui.h" #include "screensampler.H" /** Store a importon/poton. Some acceptance tests are performed first **/ static bool HasDiffuseOrGlossy(CPathNode *node) { if(node->m_hit.patch->surface->material) { BSDF *bsdf = node->m_hit.patch->surface->material->bsdf; return !ZeroAlbedo(bsdf, &node->m_hit, BSDF_DIFFUSE_COMPONENT|BSDF_GLOSSY_COMPONENT); } else return false; } static bool BounceDiffuseOrGlossy(CPathNode *node) { return node->m_usedComponents & (BSDF_DIFFUSE_COMPONENT|BSDF_GLOSSY_COMPONENT); } static bool DoImportanceStore(CImportanceMap *map, CPathNode *node, COLOR importance) { if(HasDiffuseOrGlossy(node)) { float importanceF = COLORAVERAGE(importance); float potentialF = 1.0; // COLORAVERAGE(potential)*Ax; // Compute footprint float footprintF = 1.0; CImporton importon(node->m_hit.point, importanceF, potentialF, footprintF, node->m_inDirF); return map->AddPhoton(importon, node->m_hit.normal, 0); } else return false; } /** -- Handle one potential path : store at all end points in direct readout importance map (TODO...) and at the end point in the indirect readout importance map. **/ void HandlePotentialPath(PMAPCONFIG *config) { CBiPath *bp = &config->bipath; COLOR accImportance; // Importance : integration // Store first diffuse/glossy -> direct importance map // Store last node -> indirect importance map // tracing made sure importance is low enough for the indirect importance map // bp->m_eyeSize = 1; CPathNode *currentNode = bp->m_eyePath; CPathNode *prevNode = NULL; bp->m_geomConnect = 1.0; // No connection yet (not needed) COLORSETMONOCHROME(accImportance, 1.0); bool isLastNode = false; int DGBounces = 0; // Iterate while(!isLastNode) { // Adjust importance float factor = currentNode->m_G / currentNode->m_pdfFromPrev; COLORSCALE(factor, accImportance, accImportance); if(prevNode) // Skip the eye node { // Check if direct importance if(DGBounces == 0) { // No diffuse or glossy bounce yet: direct importance map // DoImportanceStore(pmapconfig->importanceCMap, currentNode, importance); } } // Next node if(currentNode->Ends()) isLastNode = true; else { COLORPROD(currentNode->m_bsdfEval, accImportance, accImportance); if(currentNode->m_usedComponents & (BSDF_DIFFUSE_COMPONENT|BSDF_GLOSSY_COMPONENT)) DGBounces++; currentNode = currentNode->Next(); } } // currentnode is the last node in the path if(DGBounces > 0) { // It's an indirect photon DoImportanceStore(config->importanceMap, currentNode, accImportance); } } // Returns whether a valid potential path was returned. static bool TracePotentialPath(PMAPCONFIG *config) { CPathNode *path = config->bipath.m_eyePath; CSamplerConfig &scfg = config->eyeConfig; // Eye node path = scfg.TraceNode(path, drand48(), drand48(), BSDF_ALL_COMPONENTS); if(path == NULL) return false; config->bipath.m_eyePath = path; // In case no nodes were present COLOR accImportance; // Track importance along the ray COLORSETMONOCHROME(accImportance, 1.0); // Adjust importance for eye ray float factor = path->m_G / path->m_pdfFromPrev; COLORSCALE(factor, accImportance, accImportance); int DGBounces = 0; // Number of diffuse/glossy bounces bool indirectImportance = false; // Can we store in the indirect importance map // New node path->EnsureNext(); CPathNode *node = path->Next(); // Keep tracing nodes until sampling fails, store importons along the way double x_1, x_2; x_1 = drand48(); x_2 = drand48(); while(scfg.TraceNode(node, x_1, x_2, (indirectImportance ? BSDF_SPECULAR_COMPONENT : BSDF_ALL_COMPONENTS))) { // Succesful trace CPathNode *prev = node->Previous(); // Determine scatter type bool didDG = BounceDiffuseOrGlossy(prev); bool tooClose = (node->m_G > pmapstate.gThreshold); if(didDG) { DGBounces++; if(!tooClose) indirectImportance = true; } // Adjust importance COLORPROD(prev->m_bsdfEval, accImportance, accImportance); factor = node->m_G / node->m_pdfFromPrev; COLORSCALE(factor, accImportance, accImportance); // Store in map CImportanceMap *imap = (indirectImportance ? config->importanceMap : config->importanceCMap); if(imap) DoImportanceStore(imap, node, accImportance); // New node node->EnsureNext(); node = node->Next(); x_1 = drand48(); x_2 = drand48(); } // fprintf(stderr, "DGBounces %i\n", DGBounces); return true; } void TracePotentialPaths(int nrPaths) { int i; // Fill in config structures pmapconfig.eyeConfig.maxDepth = 7; // Maximum of 4 specular bounces pmapconfig.eyeConfig.minDepth = 3; CPathNode::m_dmaxsize = 0; // No need for derivative structures for(i = 0; i < nrPaths; i++) { // fprintf(stderr, "Path %i\n", i); TracePotentialPath(&pmapconfig); if (pmapstate.wake_up) { ProcessWaitingEvents(); pmapstate.wake_up = FALSE; } } pmapconfig.eyeConfig.maxDepth = 1; // Back to NEE state pmapconfig.eyeConfig.minDepth = 1; }