void PathCPURenderThread::DirectLightSampling( const float u0, const float u1, const float u2, const float u3, const float u4, const Spectrum &pathThrouput, const BSDF &bsdf, const int depth, Spectrum *radiance) { PathCPURenderEngine *engine = (PathCPURenderEngine *)renderEngine; Scene *scene = engine->renderConfig->scene; if (!bsdf.IsDelta()) { // Pick a light source to sample float lightPickPdf; const LightSource *light = scene->SampleAllLights(u0, &lightPickPdf); Vector lightRayDir; float distance, directPdfW; Spectrum lightRadiance = light->Illuminate(scene, bsdf.hitPoint, u1, u2, u3, &lightRayDir, &distance, &directPdfW); if (!lightRadiance.Black()) { BSDFEvent event; float bsdfPdfW; Spectrum bsdfEval = bsdf.Evaluate(lightRayDir, &event, &bsdfPdfW); if (!bsdfEval.Black()) { const float epsilon = Max(MachineEpsilon::E(bsdf.hitPoint), MachineEpsilon::E(distance)); Ray shadowRay(bsdf.hitPoint, lightRayDir, epsilon, distance - epsilon); RayHit shadowRayHit; BSDF shadowBsdf; Spectrum connectionThroughput; // Check if the light source is visible if (!scene->Intersect(device, false, u4, &shadowRay, &shadowRayHit, &shadowBsdf, &connectionThroughput)) { const float cosThetaToLight = AbsDot(lightRayDir, bsdf.shadeN); const float directLightSamplingPdfW = directPdfW * lightPickPdf; const float factor = cosThetaToLight / directLightSamplingPdfW; if (depth >= engine->rrDepth) { // Russian Roulette bsdfPdfW *= Max(bsdfEval.Filter(), engine->rrImportanceCap); } // MIS between direct light sampling and BSDF sampling const float weight = PowerHeuristic(directLightSamplingPdfW, bsdfPdfW); *radiance += (weight * factor) * pathThrouput * connectionThroughput * lightRadiance * bsdfEval; } } } } }
void PathHybridState::DirectLightSampling(const PathHybridRenderThread *renderThread, const float u0, const float u1, const float u2, const float u3, const BSDF &bsdf) { if (!bsdf.IsDelta()) { PathHybridRenderEngine *renderEngine = (PathHybridRenderEngine *)renderThread->renderEngine; Scene *scene = renderEngine->renderConfig->scene; // Pick a light source to sample float lightPickPdf; const LightSource *light = scene->SampleAllLights(u0, &lightPickPdf); Vector lightRayDir; float distance, directPdfW; Spectrum lightRadiance = light->Illuminate(*scene, bsdf.hitPoint.p, u1, u2, u3, &lightRayDir, &distance, &directPdfW); if (!lightRadiance.Black()) { BSDFEvent event; float bsdfPdfW; Spectrum bsdfEval = bsdf.Evaluate(lightRayDir, &event, &bsdfPdfW); if (!bsdfEval.Black()) { const float epsilon = Max(MachineEpsilon::E(bsdf.hitPoint.p), MachineEpsilon::E(distance)); directLightRay = Ray(bsdf.hitPoint.p, lightRayDir, epsilon, distance - epsilon); const float cosThetaToLight = AbsDot(lightRayDir, bsdf.hitPoint.shadeN); const float directLightSamplingPdfW = directPdfW * lightPickPdf; const float factor = cosThetaToLight / directLightSamplingPdfW; if (depth >= renderEngine->rrDepth) { // Russian Roulette bsdfPdfW *= RenderEngine::RussianRouletteProb(bsdfEval, renderEngine->rrImportanceCap); } // MIS between direct light sampling and BSDF sampling const float weight = PowerHeuristic(directLightSamplingPdfW, bsdfPdfW); directLightRadiance = (weight * factor) * throuput * lightRadiance * bsdfEval; } else directLightRadiance = Spectrum(); } else directLightRadiance = Spectrum(); } else directLightRadiance = Spectrum(); }