glm::vec3 BidirectionalIntegrator::TraceRay(Ray r, unsigned int depth) { Intersection isx = intersection_engine->GetIntersection(r); if(isx.t < 0) return glm::vec3(0); else if(isx.object_hit->material->is_light_source) { return isx.object_hit->material->base_color * isx.texture_color; } glm::vec3 resultColor(0); for(Geometry* light : scene->lights) { std::vector<PathNode> eyePath = generateEyePath(r); std::vector<PathNode> lightPath = generateLightPath(light); if(!eyePath.empty() && !lightPath.empty()) { PathNode* node = &lightPath[0]; float lightPdf = light->RayPDF(node->isx,Ray(node->isx.point,node->dirIn_world)); glm::vec3 Le(0); if(lightPdf != 0) Le = light->material->base_color * light->material->intensity / lightPdf; glm::vec3 directWt(1.0f); for(int i=1;i<=eyePath.size();i++) { node = &eyePath[i-1]; Ray ray(light->transform.position(), - node->dirIn_world); resultColor += directWt * EstimateDirectLight(node->isx, ray, light) / WeightPath(i,0); directWt *= node->F * glm::abs(glm::dot(node->dirOut_world,node->isx.normal)) / node->pdf; for(int j=1;j<=lightPath.size();j++) { resultColor += Le * EvaluatePath(eyePath,i,lightPath,j) / WeightPath(i,j); } } } else { continue; } } return resultColor; }
Spectrum VolumePatIntegrator::UniformSampleLight(const Scene *scene, const Renderer *renderer, MemoryArena &arena, const Point &p, const Normal &n, const Vector &wo, float rayEpsilon, float time, RNG &rng) const { // Randomly choose a single light to sample, _light_ int nLights = int(scene->lights.size()); if (nLights == 0) return Spectrum(0.); int lightNum; lightNum = Floor2Int(rng.RandomFloat() * nLights); lightNum = min(lightNum, nLights-1); Light *light = scene->lights[lightNum]; // Initialize light sample for single light sampling LightSample lightSample(rng); return (float) nLights * EstimateDirectLight(scene, renderer, arena, light, p, n, wo, rayEpsilon, time, rng, lightSample); }