Col3f PathTraceIntegrator::Li(const LightPath& lightPathOrig, const Ref<BackendScene>& scene, Sampler* sampler, size_t& numRays) { bool done = false; Col3f coeff = Col3f(1,1,1); Col3f Lsum = zero; Col3f L = zero; LightPath lightPath = lightPathOrig; bool doneDiffuse = false; /*! while cycle instead of the recusrion call * throughput is accumulated and the resulting light addition is * multipliled by this throughput (coef) at each itteration */ while (!done) { BRDFType directLightingBRDFTypes = (BRDFType)(DIFFUSE); BRDFType giBRDFTypes = (BRDFType)(ALL); /*! Terminate path if too long or contribution too low. */ L = zero; /*! Terminate the path if maxDepth is reached */ if (lightPath.depth >= maxDepth) // || reduce_max(coeff) < minContribution) return Lsum; /*! Traverse ray. */ DifferentialGeometry dg; scene->accel->intersect(lightPath.lastRay,dg); scene->postIntersect(lightPath.lastRay,dg); const Vec3f wo = -lightPath.lastRay.dir; numRays++; /*! Environment shading when nothing hit. */ if (!dg) { if (backplate && lightPath.unbend) { Vec2f raster = sampler->getPrimary(); int width = sampler->getImageSize().x; int height = sampler->getImageSize().y; int x = (int)((raster.x / width) * backplate->width); x = clamp(x, 0, int(backplate->width)-1); int y = (int)((raster.y / height) * backplate->height); y = clamp(y, 0, int(backplate->height)-1); L = backplate->get(x, y); } else { if (!lightPath.ignoreVisibleLights) for (size_t i=0; i<scene->envLights.size(); i++) L += scene->envLights[i]->Le(wo); } return Lsum + L*coeff; } /*! Shade surface. */ CompositedBRDF brdfs; if (dg.material) dg.material->shade(lightPath.lastRay, lightPath.lastMedium, dg, brdfs); /*! face forward normals */ bool backfacing = false; #if defined(__EMBREE_CONSISTENT_NORMALS__) && __EMBREE_CONSISTENT_NORMALS__ > 1 return Col3f(abs(dg.Ns.x),abs(dg.Ns.y),abs(dg.Ns.z)); #else if (dot(dg.Ng, lightPath.lastRay.dir) > 0) { backfacing = true; dg.Ng = -dg.Ng; dg.Ns = -dg.Ns; } #endif /*! Sample BRDF - get the sample direction for * both the indirect illumination as well as for the MIS BRDF sampling */ Col3f c; Sample3f wi;BRDFType type; Vec2f s = sampler->getVec2f(firstScatterSampleID + lightPath.depth); float ss = sampler->getFloat(firstScatterTypeSampleID + lightPath.depth); c = brdfs.sample(wo, dg, wi, type, s, ss, giBRDFTypes); /*! Add light emitted by hit area light source. */ if (!lightPath.ignoreVisibleLights && dg.light && !backfacing) L += dg.light->Le(dg,wo); /*! Check if any BRDF component uses direct lighting. */ bool useDirectLighting = false; for (size_t i=0; i<brdfs.size(); i++) useDirectLighting |= (brdfs[i]->type & directLightingBRDFTypes) != NONE; /*! Direct lighting. */ if (useDirectLighting) { std::vector<float> illumFactor; // illumination factor for each ls float sum = 0; LightSample ls; if ( wi.pdf > 0.0f ) { Ray r( dg.P, wi.value, dg.error*epsilon, inf ); DifferentialGeometry diff; scene->accel->intersect( r, diff ); scene->postIntersect( r, diff ); // Col3f red = Col3f( 1.0f, 0.0f, 0.0f); Col3f radiance = Col3f( 0.0f,0.0f,0.0f ); if ( diff.light ) // if BRDF sampling hits the light { radiance = diff.light->Le(diff, -wi.value ); } if ( dot( diff.Ng, -r.dir ) > 0 && type != GLOSSY_REFLECTION) L += radiance * c / wi.pdf; } /*! Run through all the lightsources and sample or compute the distribution function for rnd gen */ for (size_t i=0; i<scene->allLights.size(); i++) { /*! Either use precomputed samples for the light or sample light now. */ if (scene->allLights[i]->precompute()) ls = sampler->getLightSample(precomputedLightSampleID[i]); else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, sampler->getVec2f(lightSampleID)); /*! Start using only one random lightsource after first Lambertian reflection * in case of the direct illumination MIS this heuristics is ommited */ if (true)//donedif { /*! run through all the lighsources and compute radiance accumulatively */ float boo = reduce_max(ls.L)/ls.tMax; // incomming illuminance heuristic sum += boo; illumFactor.push_back(boo); // illumination factor } else // if all the lights are sampled - take each sample and compute the addition { /*! Ignore zero radiance or illumination from the back. */ if (ls.L == Col3f(zero) || ls.wi.pdf == 0.0f || dot(dg.Ns,Vec3f(ls.wi)) <= 0.0f) continue; /*! Test for shadows. */ bool inShadow = scene->accel->occluded(Ray(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon)); numRays++; if (inShadow) continue; /*! Evaluate BRDF. */ L += ls.L * brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes) * rcp(ls.wi.pdf); } } /*! After fisrt Lambertian reflection pick one random lightsource and compute contribution * in case of MIS active this heuristic is ommited */ if (true && scene->allLights.size() != 0)//donedif { /*! Generate the random value */ unsigned int RndVal; // random value // if (rand_s(&RndVal)) std::cout << "\nRND gen error!\n"; rand_r(&RndVal); float rnd((float)RndVal/(float)UINT_MAX); // compute the 0-1 rnd value /*! Pick the particular lightsource according the intensity-given distribution */ size_t i = 0; float accum = illumFactor[i]/sum; // accumulative sum while (i < scene->allLights.size() && rnd > accum) // get the lightsource index accirding the Pr { ++i; accum +=illumFactor[i]/sum; } /*! Sample the selected lightsource and compute contribution */ if ( i >= scene->allLights.size() ) i = scene->allLights.size() -1; // if (usedLight != NULL) // std::cout << "direct light " << scene->allLights[i].ptr << "\n"; float ql = illumFactor[i]/sum; // Pr of given lightsource // LightSample ls; if (scene->allLights[i]->precompute()) ls = sampler->getLightSample(precomputedLightSampleID[i]); else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, sampler->getVec2f(lightSampleID)); /*! Ignore zero radiance or illumination from the back. */ if (ls.L != Col3f(zero) && ls.wi.pdf != 0.0f && dot(dg.Ns,Vec3f(ls.wi)) > 0.0f) { /*! Test for shadows. */ bool inShadow = scene->accel->occluded(Ray(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon)); numRays++; if (!inShadow) { /*! Evaluate BRDF. */ L += ls.L * brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes) * rcp(ls.wi.pdf*ql) * weight; } } } } /* Add the resulting light */ Lsum += coeff * L; /*! Global illumination. Pick one BRDF component and sample it. */ if (lightPath.depth < maxDepth) //always true { /*! Continue only if we hit something valid. */ if (c != Col3f(zero) && wi.pdf > 0.0f) { /*! detect the first diffuse */ if (wi.pdf < 0.33) doneDiffuse = true; /*! Compute simple volumetric effect. */ const Col3f& transmission = lightPath.lastMedium.transmission; if (transmission != Col3f(one)) c *= pow(transmission,dg.t); /*! Tracking medium if we hit a medium interface. */ Medium nextMedium = lightPath.lastMedium; if (type & TRANSMISSION) nextMedium = dg.material->nextMedium(lightPath.lastMedium); /*! Continue the path. */ float q = 1; if (doneDiffuse) { //std::cout << "\ndifusni\n"; q = min(abs(reduce_max(c) * rcp(wi.pdf)), (float)1); // std::cout << q << "\n"; unsigned int RndVal; // if (rand_s(&RndVal)) std::cout << "\nRND gen error!\n"; rand_r(&RndVal); if ((float)RndVal/(float)UINT_MAX > q) { // std::cout << "konec"; return Lsum;// + L*coeff; } } /*! Continue the path */ lightPath = lightPath.extended(Ray(dg.P, wi, dg.error*epsilon, inf), nextMedium, c, (type & directLightingBRDFTypes) != NONE); coeff = coeff * c * rcp(q * wi.pdf); }else done = true; // end the path } } return Lsum; }
Color vplIntegrator::Li(LightPath& lightPath, const Ref<BackendScene>& scene, IntegratorState& state) { /*! Traverse ray. */ DifferentialGeometry dg; //scene->intersector->intersect(lightPath.lastRay); rtcIntersect(scene->scene,(RTCRay&)lightPath.lastRay); scene->postIntersect(lightPath.lastRay,dg); state.numRays++; Color L = zero; const Vector3f wo = -lightPath.lastRay.dir; BRDFType directLightingBRDFTypes = (BRDFType)(ALL); /*! Environment shading when nothing hit. */ if (!lightPath.lastRay) { if (backplate && lightPath.unbend) { const int x = clamp(int(state.pixel.x * backplate->width ), 0, int(backplate->width )-1); const int y = clamp(int(state.pixel.y * backplate->height), 0, int(backplate->height)-1); L = backplate->get(x, y); } else { if (!lightPath.ignoreVisibleLights) for (size_t i=0; i<scene->envLights.size(); i++) L += scene->envLights[i]->Le(wo); } return L; } /*! face forward normals */ bool backfacing = false; if (dot(dg.Ng, lightPath.lastRay.dir) > 0) { backfacing = true; dg.Ng = -dg.Ng; dg.Ns = -dg.Ns; } /*! Shade surface. */ CompositedBRDF brdfs; if (dg.material) dg.material->shade(lightPath.lastRay, lightPath.lastMedium, dg, brdfs); /*! Add light emitted by hit area light source. */ if (!lightPath.ignoreVisibleLights && dg.light && !backfacing) L += dg.light->Le(dg,wo); /*! Check if any BRDF component uses direct lighting. */ bool useDirectLighting = false; for (size_t i=0; i<brdfs.size(); i++) useDirectLighting |= (brdfs[i]->type & directLightingBRDFTypes) != NONE; /*! Direct lighting. Shoot shadow rays to all light sources. */ if (useDirectLighting) { for (size_t i=0; i<scene->vpls.size(); i++) { LightSample ls; ls.L = scene->vpls[i].sample(dg, ls.wi, ls.tMax); /*! Ignore zero radiance or illumination from the back. */ //if (ls.L == Color(zero) || ls.wi.pdf == 0.0f || dot(dg.Ns,Vector3f(ls.wi)) <= 0.0f) continue; if (ls.L == Color(zero) || ls.wi.pdf == 0.0f) continue; /*! Evaluate BRDF */ Color brdf = brdfs.eval(wo, dg, ls.wi, ALL); if (brdf == Color(zero)) continue; /*! Test for shadows. */ Ray shadowRay(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon, lightPath.lastRay.time,dg.shadowMask); TIMESTART(stats.atomic.timeRT,rt0); rtcOccluded(scene->scene,(RTCRay&)shadowRay); TIMESTOP(stats.atomic.timeRT,rt0); state.numRays++; if (shadowRay) continue; /*! Evaluate BRDF. */ L += ls.L * brdf * rcp(ls.wi.pdf); } } return L; }
Color PathTraceIntegrator::Li(LightPath& lightPath, const Ref<BackendScene>& scene, IntegratorState& state) { /*! Terminate path if too long or contribution too low. */ if (lightPath.depth >= maxDepth || reduce_max(lightPath.throughput) < minContribution) return zero; /*! Traverse ray. */ DifferentialGeometry dg; //scene->intersector->intersect(lightPath.lastRay); rtcIntersect(scene->scene,(RTCRay&)lightPath.lastRay); scene->postIntersect(lightPath.lastRay,dg); state.numRays++; //return Color(dg.st.x,dg.st.y,0.0f); Color L = zero; const Vector3f wo = -lightPath.lastRay.dir; BRDFType directLightingBRDFTypes = (BRDFType)(DIFFUSE); BRDFType giBRDFTypes = (BRDFType)(ALL); if (sampleLightForGlossy) { directLightingBRDFTypes = (BRDFType)(DIFFUSE|GLOSSY); giBRDFTypes = (BRDFType)(SPECULAR); } /*! Environment shading when nothing hit. */ if (!lightPath.lastRay) { if (backplate && lightPath.unbend) { const int x = clamp(int(state.pixel.x * backplate->width ), 0, int(backplate->width )-1); const int y = clamp(int(state.pixel.y * backplate->height), 0, int(backplate->height)-1); L = backplate->get(x, y); } else { if (!lightPath.ignoreVisibleLights) for (size_t i=0; i<scene->envLights.size(); i++) L += scene->envLights[i]->Le(wo); } return L; } /*! face forward normals */ bool backfacing = false; if (dot(dg.Ng, lightPath.lastRay.dir) > 0) { backfacing = true; dg.Ng = -dg.Ng; dg.Ns = -dg.Ns; } /*! Shade surface. */ CompositedBRDF brdfs; if (dg.material) dg.material->shade(lightPath.lastRay, lightPath.lastMedium, dg, brdfs); /*! Add light emitted by hit area light source. */ if (!lightPath.ignoreVisibleLights && dg.light && !backfacing) L += dg.light->Le(dg,wo); /*! Global illumination. Pick one BRDF component and sample it. */ if (lightPath.depth < maxDepth) { /*! sample brdf */ Sample3f wi; BRDFType type; Vec2f s = state.sample->getVec2f(firstScatterSampleID + lightPath.depth); float ss = state.sample->getFloat(firstScatterTypeSampleID + lightPath.depth); Color c = brdfs.sample(wo, dg, wi, type, s, ss, giBRDFTypes); /*! Continue only if we hit something valid. */ if (c != Color(zero) && wi.pdf > 0.0f) { /*! Compute simple volumetric effect. */ const Color& transmission = lightPath.lastMedium.transmission; if (transmission != Color(one)) c *= pow(transmission,lightPath.lastRay.tfar); /*! Tracking medium if we hit a medium interface. */ Medium nextMedium = lightPath.lastMedium; if (type & TRANSMISSION) nextMedium = dg.material->nextMedium(lightPath.lastMedium); /*! Continue the path. */ LightPath scatteredPath = lightPath.extended(Ray(dg.P, wi, dg.error*epsilon, inf, lightPath.lastRay.time), nextMedium, c, (type & directLightingBRDFTypes) != NONE); L += c * Li(scatteredPath, scene, state) * rcp(wi.pdf); } } /*! Check if any BRDF component uses direct lighting. */ bool useDirectLighting = false; for (size_t i=0; i<brdfs.size(); i++) useDirectLighting |= (brdfs[i]->type & directLightingBRDFTypes) != NONE; /*! Direct lighting. Shoot shadow rays to all light sources. */ if (useDirectLighting) { for (size_t i=0; i<scene->allLights.size(); i++) { if ((scene->allLights[i]->illumMask & dg.illumMask) == 0) continue; /*! Either use precomputed samples for the light or sample light now. */ LightSample ls; if (scene->allLights[i]->precompute()) ls = state.sample->getLightSample(precomputedLightSampleID[i]); else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, state.sample->getVec2f(lightSampleID)); /*! Ignore zero radiance or illumination from the back. */ //if (ls.L == Color(zero) || ls.wi.pdf == 0.0f || dot(dg.Ns,Vector3f(ls.wi)) <= 0.0f) continue; if (ls.L == Color(zero) || ls.wi.pdf == 0.0f) continue; /*! Evaluate BRDF */ Color brdf = brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes); if (brdf == Color(zero)) continue; /*! Test for shadows. */ Ray shadowRay(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon, lightPath.lastRay.time,dg.shadowMask); rtcOccluded(scene->scene,(RTCRay&)shadowRay); state.numRays++; if (shadowRay) continue; /*! Evaluate BRDF. */ L += ls.L * brdf * rcp(ls.wi.pdf); } } return L; }