@@ -340,6 +340,10 @@ void BiDirCPURenderThread::ConnectToEye(const float time,
340340 BiDirCPURenderEngine *engine = (BiDirCPURenderEngine *)renderEngine;
341341 auto & scene = engine->renderConfig .GetScene ();
342342
343+ // Test if the point-camera connection is valid
344+ float filmX, filmY;
345+ bool sampleSuccess;
346+ Ray eyeRay;
343347 Vector eyeDir;
344348 float eyeDistance = 0 ;
345349 if (scene.GetCamera ().GetType () == Camera::ORTHOGRAPHIC){
@@ -351,91 +355,90 @@ void BiDirCPURenderThread::ConnectToEye(const float time,
351355 const float D = -eyeDir.x *lensPoint.x - eyeDir.y *lensPoint.y - eyeDir.z *lensPoint.z ;
352356 eyeDistance = eyeDir.x *p.x + eyeDir.y *p.y + eyeDir.z *p.z + D;
353357 eyeDistance = fabsf (eyeDistance);
358+ eyeRay = Ray (lightVertex.bsdf .hitPoint .p , eyeDir,
359+ 0 .f ,
360+ eyeDistance,
361+ time);
362+ // Do not clamp the ray here because of the check inside ProjectToImage
363+ sampleSuccess = scene.GetCamera ().ProjectToImage (&eyeRay, &filmX, &filmY);
354364 } else {
355365 eyeDir = Vector (lightVertex.bsdf .hitPoint .p - lensPoint);
356366 eyeDistance = eyeDir.Length ();
357367 eyeDir /= eyeDistance;
368+ eyeRay = Ray (lensPoint, eyeDir,
369+ 0 .f ,
370+ eyeDistance,
371+ time);
372+ // Do not clamp the ray here because of the check inside GetSamplePosition
373+ sampleSuccess = scene.GetCamera ().GetSamplePosition (&eyeRay, &filmX, &filmY);
358374 }
359375
376+ if (!sampleSuccess)
377+ return ;
378+
379+ // Test if the bsdf evaluates to black
360380 float bsdfPdfW, bsdfRevPdfW;
361381 BSDFEvent event;
362382 const Spectrum bsdfEval = lightVertex.bsdf .Evaluate (-eyeDir, &event, &bsdfPdfW, &bsdfRevPdfW);
363383
364- if (!bsdfEval.Black ()) {
365- float filmX, filmY;
366- bool sampleSuccess;
367- Ray eyeRay;
368-
369- if (scene.GetCamera ().GetType () == Camera::ORTHOGRAPHIC){
370- eyeRay = Ray (lightVertex.bsdf .hitPoint .p , eyeDir,
371- 0 .f ,
372- eyeDistance,
373- time);
374- // Do not clamp the ray here because of the check inside ProjectToImage
375- sampleSuccess = scene.GetCamera ().ProjectToImage (&eyeRay, &filmX, &filmY);
376- } else {
377- eyeRay = Ray (lensPoint, eyeDir,
378- 0 .f ,
379- eyeDistance,
380- time);
381- // Do not clamp the ray here because of the check inside GetSamplePosition
382- sampleSuccess = scene.GetCamera ().GetSamplePosition (&eyeRay, &filmX, &filmY);
383- }
384- if (sampleSuccess) {
385- // I have to flip the direction of the traced ray because
386- // the information inside PathVolumeInfo are about the path from
387- // the light toward the camera (i.e. ray.o would be in the wrong
388- // place).
389- scene.GetCamera ().ClampRay (&eyeRay); // Clamp the ray here (see comment above)
390- Ray traceRay (lightVertex.bsdf .GetRayOrigin (-eyeRay.d ), -eyeRay.d ,
391- eyeDistance - eyeRay.maxt ,
392- eyeDistance - eyeRay.mint ,
393- time);
394- RayHit traceRayHit;
395-
396- BSDF bsdfConn;
397- Spectrum connectionThroughput;
398- PathVolumeInfo volInfo = lightVertex.volInfo ; // I need to use a copy here
399- if (!scene.Intersect (device, LIGHT_RAY | CAMERA_RAY, &volInfo, u0, &traceRay, &traceRayHit, &bsdfConn,
400- &connectionThroughput)) {
401- // Nothing was hit, the light path vertex is visible
384+ if (bsdfEval.Black ())
385+ return ;
402386
403- if (lightVertex.depth >= engine->rrDepth ) {
404- // Russian Roulette
405- const float prob = RenderEngine::RussianRouletteProb (bsdfEval, engine->rrImportanceCap );
406- bsdfRevPdfW *= prob;
407- }
387+ // Trace a shadow ray
388+ scene.GetCamera ().ClampRay (&eyeRay); // Clamp the ray here (see comment above)
389+ // I have to flip the direction of the traced ray because
390+ // the information inside PathVolumeInfo are about the path from
391+ // the light toward the camera (i.e. ray.o would be in the wrong
392+ // place).
393+ Ray traceRay (lightVertex.bsdf .GetRayOrigin (-eyeRay.d ), -eyeRay.d ,
394+ eyeDistance - eyeRay.maxt ,
395+ eyeDistance - eyeRay.mint ,
396+ time);
397+ traceRay.UpdateMinMaxWithEpsilon ();
398+
399+ RayHit traceRayHit;
400+ BSDF bsdfConn;
401+ Spectrum connectionThroughput;
402+ PathVolumeInfo volInfo = lightVertex.volInfo ; // I need to use a copy here
403+ const bool shadowIntersection = scene.Intersect (device, LIGHT_RAY | CAMERA_RAY, &volInfo, u0, &traceRay, &traceRayHit, &bsdfConn,
404+ &connectionThroughput);
405+
406+ if (shadowIntersection)
407+ return ;
408408
409- const float cosToCamera = Dot (lightVertex.bsdf .hitPoint .shadeN , -eyeDir);
410- float cameraPdfW, fluxToRadianceFactor;
411- scene.GetCamera ().GetPDF (eyeRay, eyeDistance, filmX, filmY, &cameraPdfW, &fluxToRadianceFactor);
412- const float cameraPdfA = PdfWtoA (cameraPdfW, eyeDistance, cosToCamera);
413- // Was:
414- // const float fluxToRadianceFactor = cameraPdfA;
415- //
416- // but now BSDF::Evaluate() follows LuxRender habit to return the
417- // result multiplied by cosThetaToLight
418- //
419- // However this is not true for volumes (see bug
420- // report http://forums.luxcorerender.org/viewtopic.php?f=4&t=1146&start=10#p13491)
421- fluxToRadianceFactor *= lightVertex.bsdf .IsVolume () ? fabsf (cosToCamera) : 1 .f ;
422-
423- const float weightLight = MIS (cameraPdfA) *
424- (misVmWeightFactor + lightVertex.dVCM + lightVertex.dVC * MIS (bsdfRevPdfW));
425- const float misWeight = 1 .f / (weightLight + 1 .f );
426-
427- const Spectrum radiance = (misWeight * fluxToRadianceFactor) *
428- connectionThroughput * lightVertex.throughput * bsdfEval;
429-
430- SampleResult &sampleResult = AddResult (sampleResults, true );
431- sampleResult.filmX = filmX;
432- sampleResult.filmY = filmY;
433-
434- // Add radiance from the light source
435- sampleResult.radiance [lightVertex.lightID ] = radiance;
436- }
437- }
409+ if (lightVertex.depth >= engine->rrDepth ) {
410+ // Russian Roulette
411+ const float prob = RenderEngine::RussianRouletteProb (bsdfEval, engine->rrImportanceCap );
412+ bsdfRevPdfW *= prob;
438413 }
414+
415+ const float cosToCamera = Dot (lightVertex.bsdf .hitPoint .shadeN , -eyeDir);
416+ float cameraPdfW, fluxToRadianceFactor;
417+ scene.GetCamera ().GetPDF (eyeRay, eyeDistance, filmX, filmY, &cameraPdfW, &fluxToRadianceFactor);
418+ const float cameraPdfA = PdfWtoA (cameraPdfW, eyeDistance, cosToCamera);
419+ // Was:
420+ // const float fluxToRadianceFactor = cameraPdfA;
421+ //
422+ // but now BSDF::Evaluate() follows LuxRender habit to return the
423+ // result multiplied by cosThetaToLight
424+ //
425+ // However this is not true for volumes (see bug
426+ // report http://forums.luxcorerender.org/viewtopic.php?f=4&t=1146&start=10#p13491)
427+ fluxToRadianceFactor *= lightVertex.bsdf .IsVolume () ? fabsf (cosToCamera) : 1 .f ;
428+
429+ const float weightLight = MIS (cameraPdfA) *
430+ (misVmWeightFactor + lightVertex.dVCM + lightVertex.dVC * MIS (bsdfRevPdfW));
431+ const float misWeight = 1 .f / (weightLight + 1 .f );
432+
433+ const Spectrum radiance = (misWeight * fluxToRadianceFactor) *
434+ connectionThroughput * lightVertex.throughput * bsdfEval;
435+
436+ SampleResult &sampleResult = AddResult (sampleResults, true );
437+ sampleResult.filmX = filmX;
438+ sampleResult.filmY = filmY;
439+
440+ // Add radiance from the light source
441+ sampleResult.radiance [lightVertex.lightID ] = radiance;
439442}
440443
441444void BiDirCPURenderThread::DirectLightSampling (const float time,
0 commit comments