Skip to content

Commit a3bf61b

Browse files
committed
1.[FORMATTING]
1 parent cd24589 commit a3bf61b

1 file changed

Lines changed: 148 additions & 142 deletions

File tree

src/Scene.cpp

Lines changed: 148 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <glm/gtx/norm.hpp>
88
#include <light/Light.hpp>
99
#include <light/SphereLight.hpp>
10+
#include <limits>
1011
#include <memory>
1112
#include <numeric> // For std::accumulate
1213
#include <scene/Scene.hpp>
@@ -394,7 +395,88 @@ SoftRasterizer::Intersection SoftRasterizer::Scene::traceScene(Ray &ray) {
394395
return ret;
395396
}
396397

397-
glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth, const std::size_t sample) {
398+
[[nodiscard]] std::tuple<glm::dvec3, double>
399+
SoftRasterizer::Scene::sampleLightOnCenter(const glm::vec3 &shadingPoint) {
400+
// Collect all emissive objects and approximate their bounding spheres**
401+
std::vector<std::pair<glm::dvec3, double>> lightSpheres;
402+
for (const auto &obj : m_exportedObjs) {
403+
if (obj->isSelfEmissiveObject()) {
404+
Bounds3 bbox = obj->getBounds();
405+
glm::dvec3 center = (glm::dvec3(bbox.min) + glm::dvec3(bbox.max)) * 0.5;
406+
double radius = glm::length(glm::dvec3(bbox.diagonal())) * 0.5;
407+
lightSpheres.emplace_back(center, radius);
408+
}
409+
}
410+
411+
if (lightSpheres.empty()) {
412+
spdlog::warn("No emissive objects found in the scene!");
413+
return {glm::dvec3(0.0), 0.0};
414+
}
415+
416+
// Randomly select a light source
417+
int randomIndex =
418+
static_cast<int>(Tools::random_generator() * lightSpheres.size());
419+
glm::dvec3 sphereCenter = lightSpheres[randomIndex].first;
420+
double sphereRadius = lightSpheres[randomIndex].second;
421+
422+
glm::dvec3 lightDir = glm::normalize(sphereCenter - glm::dvec3(shadingPoint));
423+
424+
// Compute probability density function (PDF)
425+
double pdf = 0.5 * Tools::PI_INV;
426+
return {lightDir, pdf};
427+
}
428+
429+
std::tuple<glm::dvec3, double>
430+
SoftRasterizer::Scene::sampleLight(const glm::vec3 &shadingPoint) {
431+
// Collect all emissive objects and approximate their bounding spheres**
432+
std::vector<std::pair<glm::dvec3, double>> lightSpheres;
433+
for (const auto &obj : m_exportedObjs) {
434+
if (obj->isSelfEmissiveObject()) {
435+
Bounds3 bbox = obj->getBounds();
436+
glm::dvec3 center = (glm::dvec3(bbox.min) + glm::dvec3(bbox.max)) * 0.5;
437+
double radius = glm::length(glm::dvec3(bbox.diagonal())) * 0.5;
438+
lightSpheres.emplace_back(center, radius);
439+
}
440+
}
441+
442+
if (lightSpheres.empty()) {
443+
spdlog::warn("No emissive objects found in the scene!");
444+
return {glm::dvec3(0.0), 0.0};
445+
}
446+
447+
// Randomly select a light source
448+
int randomIndex =
449+
static_cast<int>(Tools::random_generator() * lightSpheres.size());
450+
glm::dvec3 sphereCenter = lightSpheres[randomIndex].first;
451+
double sphereRadius = lightSpheres[randomIndex].second;
452+
453+
glm::dvec3 baselineDir =
454+
glm::normalize(sphereCenter - glm::dvec3(shadingPoint));
455+
456+
// Sample a random direction on the light source sphere
457+
glm::dvec3 sampleDir = glm::sphericalRand(1.0);
458+
if (glm::dot(sampleDir, baselineDir) < 0.0) {
459+
sampleDir = -sampleDir;
460+
}
461+
462+
// Apply random perturbation for anti-aliasing and soft shadow
463+
double perturbationStrength = 1e-6;
464+
glm::dvec3 randomPerturbation = glm::sphericalRand(perturbationStrength);
465+
sampleDir = glm::normalize(sampleDir + randomPerturbation);
466+
467+
glm::dvec3 samplePos = sphereCenter + sampleDir * sphereRadius;
468+
469+
// Compute direction from shading point to light source
470+
glm::dvec3 lightDir = glm::normalize(samplePos - glm::dvec3(shadingPoint));
471+
472+
// Compute probability density function (PDF)
473+
double cosTheta = glm::dot(lightDir, baselineDir);
474+
double pdf = 0.5 * Tools::PI_INV * cosTheta;
475+
return {lightDir, pdf};
476+
}
477+
478+
glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth,
479+
const std::size_t sample) {
398480

399481
glm::vec3 final_color = this->m_backgroundColor;
400482

@@ -408,7 +490,7 @@ glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth, const st
408490
}
409491

410492
Intersection intersection = traceScene(ray);
411-
if (!intersection.intersected || !intersection.obj) {
493+
if (!intersection.intersected) {
412494
// Return black if the ray does not intersect with any object
413495
spdlog::debug("Ray Intersection Not Found On Depth {}", depth);
414496
return this->m_backgroundColor;
@@ -427,65 +509,70 @@ glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth, const st
427509

428510
/*Phong illumation model*/
429511
if (intersection.material->getMaterialType() ==
430-
MaterialType::DIFFUSE_AND_GLOSSY) {
431-
432-
final_color = tbb::parallel_reduce(
433-
tbb::blocked_range<std::size_t>(0, sample),
434-
glm::vec3(0.0f), // Initial value
435-
[&](const tbb::blocked_range<std::size_t>& range,
436-
glm::vec3 local_sum) -> glm::vec3 {
437-
for (std::size_t i = range.begin(); i < range.end(); ++i) {
438-
auto [shading2LightDir, lightAreaPdf] = sampleLightOnCenter(hitPoint);
439-
440-
Ray lightSampleRay(hitPoint, shading2LightDir);
441-
442-
Intersection lightSampleIntersection = traceScene(lightSampleRay);
443-
if (!lightSampleIntersection.intersected){
444-
// || (lightSampleIntersection.intersected && glm::length(lightSampleIntersection.emit) < m_epsilon)) {
445-
return glm::vec3(0.f);
446-
}
447-
448-
// Diffuse reflection (Lambertian)
449-
double diff = std::max(0., glm::dot(glm::dvec3(N), shading2LightDir));
450-
451-
// Specular reflection (Blinn-Phong)
452-
glm::dvec3 reflectDir =
453-
glm::normalize(glm::reflect(-shading2LightDir, glm::dvec3(hitNormal)));
454-
double spec =
455-
std::pow(std::max(0., -glm::dot(glm::dvec3(ray.direction), reflectDir)),
456-
intersection.material->specularExponent);
457-
458-
double distanceSquare =
459-
glm::length2(hitPoint - lightSampleIntersection.coords);
460-
double timeSquare = lightSampleIntersection.intersect_time *
461-
lightSampleIntersection.intersect_time;
462-
bool is_shadow = std::abs(timeSquare - distanceSquare) > 1e-6f;
463-
464-
spdlog::debug("timeSquare={}, distanceSquare={},delta = {}, is_shadow={}",
465-
timeSquare, distanceSquare,
466-
std::abs(distanceSquare - timeSquare), is_shadow);
467-
468-
// Compute light contribution
469-
glm::vec3 ambient =
470-
!is_shadow ? lightSampleIntersection.emit : glm::vec3(0.f);
471-
glm::vec3 diffuse = !is_shadow
472-
? glm::vec3(diff) * lightSampleIntersection.emit
473-
: glm::vec3(0.f);
474-
glm::vec3 specular = spec * glm::dvec3(lightSampleIntersection.emit);
475-
476-
// Accumulate to local sum
477-
local_sum = (ambient * intersection.material->Ka) +
478-
(intersection.color * diffuse) +
479-
(specular * intersection.material->Ks);
480-
}
481-
return local_sum;
482-
},
483-
[](const glm::vec3& a, const glm::vec3& b) {
484-
return a + b;
485-
} // Combine partial results
486-
) ;
487-
488-
final_color /= sample;
512+
MaterialType::DIFFUSE_AND_GLOSSY) {
513+
514+
final_color = tbb::parallel_reduce(
515+
tbb::blocked_range<std::size_t>(0, sample),
516+
glm::vec3(0.0f), // Initial value
517+
[&](const tbb::blocked_range<std::size_t> &range,
518+
glm::vec3 local_sum) -> glm::vec3 {
519+
for (std::size_t i = range.begin(); i < range.end(); ++i) {
520+
521+
auto [shading2LightDir, lightAreaPdf] =
522+
sampleLightOnCenter(hitPoint);
523+
524+
Ray lightSampleRay(hitPoint, shading2LightDir);
525+
Intersection lightSampleIntersection = traceScene(lightSampleRay);
526+
if (!lightSampleIntersection.intersected ||
527+
(lightSampleIntersection.intersected &&
528+
glm::length(lightSampleIntersection.emit) < m_epsilon)) {
529+
return glm::vec3(0.f);
530+
}
531+
532+
// Diffuse reflection (Lambertian)
533+
double diff =
534+
std::max(0., glm::dot(glm::dvec3(N), shading2LightDir));
535+
536+
// Specular reflection (Blinn-Phong)
537+
glm::dvec3 reflectDir = glm::normalize(
538+
glm::reflect(-shading2LightDir, glm::dvec3(hitNormal)));
539+
double spec = std::pow(
540+
std::max(0., -glm::dot(glm::dvec3(ray.direction), reflectDir)),
541+
intersection.material->specularExponent);
542+
543+
double distanceSquare =
544+
glm::length2(hitPoint - lightSampleIntersection.coords);
545+
double timeSquare = lightSampleIntersection.intersect_time *
546+
lightSampleIntersection.intersect_time;
547+
bool is_shadow = std::abs(timeSquare - distanceSquare) > 1e-6f;
548+
549+
spdlog::debug(
550+
"timeSquare={}, distanceSquare={},delta = {}, is_shadow={}",
551+
timeSquare, distanceSquare,
552+
std::abs(distanceSquare - timeSquare), is_shadow);
553+
554+
// Compute light contribution
555+
glm::vec3 ambient =
556+
!is_shadow ? lightSampleIntersection.emit : glm::vec3(0.f);
557+
glm::vec3 diffuse =
558+
!is_shadow ? glm::vec3(diff) * lightSampleIntersection.emit
559+
: glm::vec3(0.f);
560+
glm::vec3 specular =
561+
spec * glm::dvec3(lightSampleIntersection.emit);
562+
563+
// Accumulate to local sum
564+
local_sum = (ambient * intersection.material->Ka) +
565+
(intersection.color * diffuse) +
566+
(specular * intersection.material->Ks);
567+
}
568+
return local_sum;
569+
},
570+
[](const glm::vec3 &a, const glm::vec3 &b) {
571+
return a + b;
572+
} // Combine partial results
573+
);
574+
575+
final_color /= sample;
489576
}
490577

491578
else if (intersection.material->getMaterialType() ==
@@ -622,87 +709,6 @@ SoftRasterizer::Scene::sampleLight() {
622709
return {intersection, pdf};
623710
}
624711

625-
[[nodiscard]] std::tuple<glm::dvec3, double>
626-
SoftRasterizer::Scene::sampleLightOnCenter(const glm::vec3& shadingPoint) {
627-
// Collect all emissive objects and approximate their bounding spheres**
628-
std::vector<std::pair<glm::dvec3, double>> lightSpheres;
629-
for (const auto& obj : m_exportedObjs) {
630-
if (obj->isSelfEmissiveObject()) {
631-
Bounds3 bbox = obj->getBounds();
632-
glm::dvec3 center = (glm::dvec3(bbox.min) + glm::dvec3(bbox.max)) * 0.5;
633-
double radius = glm::length(glm::dvec3(bbox.diagonal())) * 0.5;
634-
lightSpheres.emplace_back(center, radius);
635-
}
636-
}
637-
638-
if (lightSpheres.empty()) {
639-
spdlog::warn("No emissive objects found in the scene!");
640-
return { glm::dvec3(0.0), 0.0 };
641-
}
642-
643-
// Randomly select a light source
644-
int randomIndex =
645-
static_cast<int>(Tools::random_generator() * lightSpheres.size());
646-
glm::dvec3 sphereCenter = lightSpheres[randomIndex].first;
647-
double sphereRadius = lightSpheres[randomIndex].second;
648-
649-
// Compute direction from shading point to light source
650-
glm::dvec3 lightDir = glm::normalize(sphereCenter - glm::dvec3(shadingPoint));
651-
652-
// Compute probability density function (PDF)
653-
double pdf = 0.5 * Tools::PI_INV;
654-
return { lightDir, pdf };
655-
}
656-
657-
std::tuple<glm::dvec3, double>
658-
SoftRasterizer::Scene::sampleLight(const glm::vec3 &shadingPoint) {
659-
// Collect all emissive objects and approximate their bounding spheres**
660-
std::vector<std::pair<glm::dvec3, double>> lightSpheres;
661-
for (const auto &obj : m_exportedObjs) {
662-
if (obj->isSelfEmissiveObject()) {
663-
Bounds3 bbox = obj->getBounds();
664-
glm::dvec3 center = (glm::dvec3(bbox.min) + glm::dvec3(bbox.max)) * 0.5;
665-
double radius = glm::length(glm::dvec3(bbox.diagonal())) * 0.5;
666-
lightSpheres.emplace_back(center, radius);
667-
}
668-
}
669-
670-
if (lightSpheres.empty()) {
671-
spdlog::warn("No emissive objects found in the scene!");
672-
return {glm::dvec3(0.0), 0.0};
673-
}
674-
675-
// Randomly select a light source
676-
int randomIndex =
677-
static_cast<int>(Tools::random_generator() * lightSpheres.size());
678-
glm::dvec3 sphereCenter = lightSpheres[randomIndex].first;
679-
double sphereRadius = lightSpheres[randomIndex].second;
680-
681-
glm::dvec3 baselineDir =
682-
glm::normalize(sphereCenter - glm::dvec3(shadingPoint));
683-
684-
// Sample a random direction on the light source sphere
685-
glm::dvec3 sampleDir = glm::sphericalRand(1.0);
686-
if (glm::dot(sampleDir, baselineDir) < 0.0) {
687-
sampleDir = -sampleDir;
688-
}
689-
690-
// Apply random perturbation for anti-aliasing and soft shadow
691-
double perturbationStrength = 1e-6;
692-
glm::dvec3 randomPerturbation = glm::sphericalRand(perturbationStrength);
693-
sampleDir = glm::normalize(sampleDir + randomPerturbation);
694-
695-
glm::dvec3 samplePos = sphereCenter + sampleDir * sphereRadius;
696-
697-
// Compute direction from shading point to light source
698-
glm::dvec3 lightDir = glm::normalize(samplePos - glm::dvec3(shadingPoint));
699-
700-
// Compute probability density function (PDF)
701-
double cosTheta = glm::dot(lightDir, baselineDir);
702-
double pdf = 0.5 * Tools::PI_INV * cosTheta;
703-
return {lightDir, pdf};
704-
}
705-
706712
glm::vec3 SoftRasterizer::Scene::pathTracingDirectLight(
707713
const Intersection &shadeObjIntersection, const glm::vec3 &wo) {
708714

0 commit comments

Comments
 (0)