Skip to content

Commit cd24589

Browse files
committed
1.[ADD]:add samplelight especially on light's center(high probability) 2.[UPDATE]:add parallel_reduce function to do multiple sampling 3.[MODIFY]:add sample argument in whittedraytracing function
1 parent d0a8d8a commit cd24589

2 files changed

Lines changed: 101 additions & 52 deletions

File tree

include/scene/Scene.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,12 @@ class Scene {
117117
[[nodiscard]] std::tuple<glm::dvec3, double>
118118
sampleLight(const glm::vec3 &shadingPoint);
119119

120+
// sample the light by sphere angle and centerlized on center
121+
[[nodiscard]] std::tuple<glm::dvec3, double>
122+
sampleLightOnCenter(const glm::vec3& shadingPoint);
123+
120124
// Whitted Style Ray Tracing
121-
glm::vec3 whittedRayTracing(Ray &ray, int depth);
125+
glm::vec3 whittedRayTracing(Ray &ray, int depth, const std::size_t sample);
122126

123127
glm::vec3 pathTracingShading(const Intersection &shadeObjIntersection,
124128
const glm::vec3 &wo, int maxRecursionDepth = 5,

src/Scene.cpp

Lines changed: 96 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ SoftRasterizer::Intersection SoftRasterizer::Scene::traceScene(Ray &ray) {
394394
return ret;
395395
}
396396

397-
glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth) {
397+
glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth, const std::size_t sample) {
398398

399399
glm::vec3 final_color = this->m_backgroundColor;
400400

@@ -427,52 +427,65 @@ glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth) {
427427

428428
/*Phong illumation model*/
429429
if (intersection.material->getMaterialType() ==
430-
MaterialType::DIFFUSE_AND_GLOSSY) {
431-
432-
auto [shading2LightDir, lightAreaPdf] = sampleLight(hitPoint);
433-
434-
/*Self-Intersection Problem Avoidance*/
435-
glm::dvec3 perturbation = glm::dvec3(hitPoint) + 1e-6 * glm::dvec3(N);
436-
Ray lightSampleRay(perturbation, shading2LightDir);
437-
438-
Intersection lightSampleIntersection = traceScene(lightSampleRay);
439-
if (!lightSampleIntersection.intersected) {
440-
return glm::vec3(0.f);
441-
}
442-
443-
// Diffuse reflection (Lambertian)
444-
double diff = std::max(0., glm::dot(glm::dvec3(N), shading2LightDir));
445-
446-
// Specular reflection (Blinn-Phong)
447-
glm::dvec3 reflectDir =
448-
glm::normalize(glm::reflect(-shading2LightDir, glm::dvec3(hitNormal)));
449-
double spec =
450-
std::pow(std::max(0., -glm::dot(glm::dvec3(ray.direction), reflectDir)),
451-
intersection.material->specularExponent);
452-
453-
double distanceSquare =
454-
glm::length2(hitPoint - lightSampleIntersection.coords);
455-
double timeSquare = lightSampleIntersection.intersect_time *
456-
lightSampleIntersection.intersect_time;
457-
bool is_shadow = std::abs(timeSquare - distanceSquare) > 1e-6f;
458-
459-
spdlog::debug("timeSquare={}, distanceSquare={},delta = {}, is_shadow={}",
460-
timeSquare, distanceSquare,
461-
std::abs(distanceSquare - timeSquare), is_shadow);
462-
463-
// Compute light contribution
464-
glm::vec3 ambient =
465-
!is_shadow ? lightSampleIntersection.emit : glm::vec3(0.f);
466-
glm::vec3 diffuse = !is_shadow
467-
? glm::vec3(diff) * lightSampleIntersection.emit
468-
: glm::vec3(0.f);
469-
glm::vec3 specular = spec * glm::dvec3(lightSampleIntersection.emit);
470-
471-
// Accumulate to local sum
472-
final_color = (ambient * intersection.material->Ka) +
473-
(intersection.color * diffuse) +
474-
(specular * intersection.material->Ks);
475-
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;
476489
}
477490

478491
else if (intersection.material->getMaterialType() ==
@@ -518,14 +531,14 @@ glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth) {
518531
if (glm::length(refractPath) < 1e-6f || std::abs(kr - 1.0f) < 1e-6f) {
519532
// prevent relfection and refraction from happening at the same time
520533
Ray reflectedRay(reflectCoord, reflectPath);
521-
reflectedColor = whittedRayTracing(reflectedRay, depth + 1);
534+
reflectedColor = whittedRayTracing(reflectedRay, depth + 1, sample);
522535
kr = 1.0f;
523536
} else {
524537
Ray reflectedRay(reflectCoord, reflectPath);
525538
Ray refractedRay(refractCoord, refractPath);
526539

527-
reflectedColor = whittedRayTracing(reflectedRay, depth + 1);
528-
refractedColor = whittedRayTracing(refractedRay, depth + 1);
540+
reflectedColor = whittedRayTracing(reflectedRay, depth + 1, sample);
541+
refractedColor = whittedRayTracing(refractedRay, depth + 1, sample);
529542
}
530543

531544
final_color = glm::clamp(reflectedColor * kr + refractedColor * (1.f - kr),
@@ -548,7 +561,7 @@ glm::vec3 SoftRasterizer::Scene::whittedRayTracing(Ray &ray, int depth) {
548561

549562
Ray reflectedRay(reflectCoord, reflectPath);
550563

551-
reflectedColor = whittedRayTracing(reflectedRay, depth + 1);
564+
reflectedColor = whittedRayTracing(reflectedRay, depth + 1, sample);
552565

553566
final_color =
554567
glm::clamp(reflectedColor * kr, glm::vec3(0.0f), glm::vec3(1.0f));
@@ -609,6 +622,38 @@ SoftRasterizer::Scene::sampleLight() {
609622
return {intersection, pdf};
610623
}
611624

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+
612657
std::tuple<glm::dvec3, double>
613658
SoftRasterizer::Scene::sampleLight(const glm::vec3 &shadingPoint) {
614659
// Collect all emissive objects and approximate their bounding spheres**

0 commit comments

Comments
 (0)