Skip to content

Commit 51f2308

Browse files
committed
Reorder code, increase consistency between ConnectToEye functions of Path and BiDir
1 parent 38ed850 commit 51f2308

2 files changed

Lines changed: 124 additions & 119 deletions

File tree

src/slg/engines/bidircpu/bidircputhread.cpp

Lines changed: 75 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -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

441444
void BiDirCPURenderThread::DirectLightSampling(const float time,

src/slg/engines/pathtracer.cpp

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -713,23 +713,22 @@ void PathTracer::ConnectToEye(IntersectionDevice *device,
713713
if (bsdf.IsCameraInvisible() || bsdf.IsDelta())
714714
return;
715715

716+
// Test if the point-camera connection is valid
716717
float filmX, filmY;
717718
bool sampleSuccess;
718719
Ray eyeRay;
719-
720720
Vector eyeDir;
721721
float eyeDistance = 0;
722722
Point lensPoint = pathInfo.lensPoint;
723723
if (scene.GetCamera().GetType() == Camera::ORTHOGRAPHIC){
724-
// Orthographic camera need to be handled separately,
725-
// lensPoint can not be pre-calculated in this case
724+
// Orthographic camera needs to be handled separately,
725+
// lensPoint can not be used as a target here
726726
Point p = bsdf.hitPoint.p;
727727
eyeDir = scene.GetCamera().GetDir();
728728
// calculate distance from vertex to camera plane
729729
const float D = -eyeDir.x*lensPoint.x - eyeDir.y*lensPoint.y - eyeDir.z*lensPoint.z;
730730
eyeDistance = eyeDir.x*p.x + eyeDir.y*p.y + eyeDir.z*p.z + D;
731731
eyeDistance = fabsf(eyeDistance);
732-
733732
eyeRay = Ray(bsdf.hitPoint.p, eyeDir,
734733
0.f,
735734
eyeDistance,
@@ -740,7 +739,6 @@ void PathTracer::ConnectToEye(IntersectionDevice *device,
740739
eyeDir = Vector(bsdf.hitPoint.p - lensPoint);
741740
eyeDistance = eyeDir.Length();
742741
eyeDir /= eyeDistance;
743-
744742
eyeRay = Ray(lensPoint, eyeDir,
745743
0.f,
746744
eyeDistance,
@@ -749,56 +747,60 @@ void PathTracer::ConnectToEye(IntersectionDevice *device,
749747
sampleSuccess = scene.GetCamera().GetSamplePosition(&eyeRay, &filmX, &filmY);
750748
}
751749

752-
if (sampleSuccess) {
753-
BSDFEvent event;
754-
const Spectrum bsdfEval = bsdf.Evaluate(-eyeDir, &event);
755-
756-
if (!bsdfEval.Black()) {
757-
// I have to flip the direction of the traced ray because
758-
// the information inside PathVolumeInfo are about the path from
759-
// the light toward the camera (i.e. ray.o would be in the wrong
760-
// place).
761-
scene.GetCamera().ClampRay(&eyeRay); // Clamp the ray here (see comment above)
762-
Ray traceRay(bsdf.GetRayOrigin(-eyeRay.d), -eyeRay.d,
763-
eyeDistance - eyeRay.maxt,
764-
eyeDistance - eyeRay.mint,
765-
time);
766-
traceRay.UpdateMinMaxWithEpsilon();
767-
RayHit traceRayHit;
768-
769-
BSDF bsdfConn;
770-
Spectrum connectionThroughput;
771-
// Create a new PathVolumeInfo for the path to the light source
772-
PathVolumeInfo volInfo = pathInfo.volume;
773-
if (!scene.Intersect(device, LIGHT_RAY | CAMERA_RAY, &volInfo, u0, &traceRay, &traceRayHit, &bsdfConn,
774-
&connectionThroughput)) {
775-
// Nothing was hit, the light path vertex is visible
750+
if (!sampleSuccess)
751+
return;
776752

777-
float fluxToRadianceFactor;
778-
scene.GetCamera().GetPDF(eyeRay, eyeDistance, filmX, filmY, nullptr, &fluxToRadianceFactor);
753+
// Test if the bsdf evaluates to black
754+
BSDFEvent event;
755+
const Spectrum bsdfEval = bsdf.Evaluate(-eyeDir, &event);
779756

780-
SampleResult &sampleResult = AddLightSampleResult(sampleResults, film);
781-
sampleResult.filmX = filmX;
782-
sampleResult.filmY = filmY;
757+
if (bsdfEval.Black())
758+
return;
759+
760+
// Trace a shadow ray
761+
scene.GetCamera().ClampRay(&eyeRay); // Clamp the ray here (see comment above)
762+
// I have to flip the direction of the traced ray because
763+
// the information inside PathVolumeInfo are about the path from
764+
// the light toward the camera (i.e. ray.o would be in the wrong
765+
// place).
766+
Ray traceRay(bsdf.GetRayOrigin(-eyeRay.d), -eyeRay.d,
767+
eyeDistance - eyeRay.maxt,
768+
eyeDistance - eyeRay.mint,
769+
time);
770+
traceRay.UpdateMinMaxWithEpsilon();
771+
772+
RayHit traceRayHit;
773+
BSDF bsdfConn;
774+
Spectrum connectionThroughput;
775+
PathVolumeInfo volInfo = pathInfo.volume; // I need to use a copy here
776+
const bool shadowIntersection = scene.Intersect(device, LIGHT_RAY | CAMERA_RAY, &volInfo, u0, &traceRay, &traceRayHit, &bsdfConn,
777+
&connectionThroughput);
778+
779+
if (shadowIntersection)
780+
return;
783781

784-
sampleResult.pixelX = Floor2UInt(filmX);
785-
sampleResult.pixelY = Floor2UInt(filmY);
782+
float fluxToRadianceFactor;
783+
scene.GetCamera().GetPDF(eyeRay, eyeDistance, filmX, filmY, nullptr, &fluxToRadianceFactor);
784+
785+
SampleResult &sampleResult = AddLightSampleResult(sampleResults, film);
786+
sampleResult.filmX = filmX;
787+
sampleResult.filmY = filmY;
788+
789+
sampleResult.pixelX = Floor2UInt(filmX);
790+
sampleResult.pixelY = Floor2UInt(filmY);
786791

787792
#if !defined(NDEBUG)
788-
const u_int *subRegion = film.GetSubRegion();
793+
const u_int *subRegion = film.GetSubRegion();
789794
#endif
790-
assert (sampleResult.pixelX >= subRegion[0]);
791-
assert (sampleResult.pixelX <= subRegion[1]);
792-
assert (sampleResult.pixelY >= subRegion[2]);
793-
assert (sampleResult.pixelY <= subRegion[3]);
795+
assert (sampleResult.pixelX >= subRegion[0]);
796+
assert (sampleResult.pixelX <= subRegion[1]);
797+
assert (sampleResult.pixelY >= subRegion[2]);
798+
assert (sampleResult.pixelY <= subRegion[3]);
794799

795-
sampleResult.isCaustic = pathInfo.IsCausticPath(event, bsdf.GetGlossiness(), hybridBackForwardGlossinessThreshold);
800+
sampleResult.isCaustic = pathInfo.IsCausticPath(event, bsdf.GetGlossiness(), hybridBackForwardGlossinessThreshold);
796801

797-
// Add radiance from the light source
798-
sampleResult.radiance[light.GetID()] = connectionThroughput * flux * fluxToRadianceFactor * bsdfEval;
799-
}
800-
}
801-
}
802+
// Add radiance from the light source
803+
sampleResult.radiance[light.GetID()] = connectionThroughput * flux * fluxToRadianceFactor * bsdfEval;
802804
}
803805

804806
//------------------------------------------------------------------------------

0 commit comments

Comments
 (0)