From 44c0310c5cad022909b5752cd6b48f36a4b93ae4 Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Thu, 29 Aug 2024 22:57:13 +0200 Subject: [PATCH 1/8] avoid miss intersection in case of extreme bounding boxes --- src/geometry/aabb.cpp | 18 ++++++++++++++++++ src/geometry/aabb.hpp | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/geometry/aabb.cpp b/src/geometry/aabb.cpp index 68eabb0..38921d2 100644 --- a/src/geometry/aabb.cpp +++ b/src/geometry/aabb.cpp @@ -30,11 +30,20 @@ int AABB::LongestAxis() const } +AABB::AABB(const Interval &x, const Interval &y, const Interval &z) + : m_x{x}, m_y{y}, m_z{z} +{ + PadToMinimums(); +} + + AABB::AABB(const Point3 &a, const Point3 &b) { m_x = (a[0] <= b[0]) ? Interval(a[0], b[0]) : Interval(b[0], a[0]); m_y = (a[1] <= b[1]) ? Interval(a[1], b[1]) : Interval(b[1], a[1]); m_z = (a[2] <= b[2]) ? Interval(a[2], b[2]) : Interval(b[2], a[2]); + + PadToMinimums(); } @@ -75,3 +84,12 @@ bool AABB::Hit(const Ray &ray, const Interval &interval) const return true; } + + +void AABB::PadToMinimums() +{ + static double delta = 0.0001; + if(m_x.Size() < delta) m_x.Expand(delta); + if(m_y.Size() < delta) m_y.Expand(delta); + if(m_z.Size() < delta) m_z.Expand(delta); +} diff --git a/src/geometry/aabb.hpp b/src/geometry/aabb.hpp index ee88797..d9a66b4 100644 --- a/src/geometry/aabb.hpp +++ b/src/geometry/aabb.hpp @@ -18,7 +18,7 @@ class AABB { public: AABB() {} - AABB(const Interval& x, const Interval& y, const Interval& z): m_x{x}, m_y{y}, m_z{z} {} + AABB(const Interval& x, const Interval& y, const Interval& z); AABB(const Point3& a, const Point3& b); AABB(const AABB& aabb1, const AABB& aabb2); @@ -26,5 +26,9 @@ class AABB { const Interval& IndexToInterval(int index) const; int LongestAxis() const; + // To avoid intersection miss in case of exterme intervals, + // we pad the bounding boxes a bit + void PadToMinimums(); + static const AABB Empty, Universe; }; \ No newline at end of file From e6489e0bd67cc6a90a9e88dba1c0f408a82bfa80 Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Fri, 30 Aug 2024 01:46:30 +0200 Subject: [PATCH 2/8] add quads geometry --- src/geometry/quad.cpp | 64 +++++++++++++++++++++++++ src/geometry/quad.hpp | 38 +++++++++++++++ src/geometry/sphere.hpp | 3 +- src/main.cpp | 6 ++- src/scenes/quads_scene.cpp | 79 +++++++++++++++++++++++++++++++ src/scenes/quads_scene.hpp | 25 ++++++++++ src/scenes/solar_system_scene.cpp | 1 - 7 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 src/geometry/quad.cpp create mode 100644 src/geometry/quad.hpp create mode 100644 src/scenes/quads_scene.cpp create mode 100644 src/scenes/quads_scene.hpp diff --git a/src/geometry/quad.cpp b/src/geometry/quad.cpp new file mode 100644 index 0000000..699bdd8 --- /dev/null +++ b/src/geometry/quad.cpp @@ -0,0 +1,64 @@ + +#include "quad.hpp" + +#include "math/ray.hpp" + + +using namespace std; + + +Quad::Quad(const Point3 &q, const Vec3 &u, const Vec3 &v, shared_ptr material) + : m_q{q}, m_u{u}, m_v{v}, m_material{material} +{ + Vec3 n = m_u.Cross(m_v); + m_normal = n.Normalized(); + m_d = m_normal.Dot(m_q); + m_w = n / n.Dot(n); + + AABB diag1_aabb = AABB(m_q, m_q + m_u + m_v); + AABB diag2_aabb = AABB(m_q + m_u, m_q + m_v); + m_aabb = AABB(diag1_aabb, diag2_aabb); +} + + +bool Quad::Hit(const Ray &ray, const Interval &interval, HitRecord &outRecord) const +{ + double denominator = m_normal.Dot(ray.Direction()); + if(std::fabs(denominator) < 1e-8){ + return false; + } + + double t = (m_d - m_normal.Dot(ray.Origin())) / denominator; + + if(! interval.Contains(t)){ + return false; + } + + Vec3 intersection = ray.At(t); + + Vec3 plan_centered_hitpoint = intersection - m_q; + double alpha = m_w.Dot(plan_centered_hitpoint.Cross(m_v)); + double beta = m_w.Dot(m_u.Cross(plan_centered_hitpoint)); + + if(! IsInQuad(alpha, beta, outRecord)){ + return false; + } + + outRecord.t = t; + outRecord.hit_point = intersection; + outRecord.material = m_material; + outRecord.SetFaceNormal(ray, m_normal); + + return true; +} + + +bool Quad::IsInQuad(double alpha, double beta, HitRecord& hit_record) const { + static const Interval unit_interval = Interval(0.0, 1.0); + + // set it anyway to make code branchless + hit_record.u = alpha; + hit_record.v = beta; + + return unit_interval.Contains(alpha) && unit_interval.Contains(beta); +} \ No newline at end of file diff --git a/src/geometry/quad.hpp b/src/geometry/quad.hpp new file mode 100644 index 0000000..0f6c981 --- /dev/null +++ b/src/geometry/quad.hpp @@ -0,0 +1,38 @@ + +#pragma once + + +#include "geometry/IHittable.hpp" + +#include "math/vec.hpp" + + +class Quad : public IHittable { + +private: + + Point3 m_q; + Vec3 m_u; + Vec3 m_v; + + Vec3 m_normal; + // d is the intersection equation result for the plan + // for a point Q on the plane, n.Q = d + double m_d; + // w is a constant for a given quadrilateral + // It simplifies the check to know if we are inside the quad + Vec3 m_w; + + AABB m_aabb; + std::shared_ptr m_material; + + bool IsInQuad(double alpha, double beta, HitRecord& hit_record) const; + + +public: + + Quad(const Point3& q, const Vec3& u, const Vec3& v, std::shared_ptr material); + + bool Hit(const Ray& ray, const Interval& interval, HitRecord& outRecord) const override; + AABB GetAABB() const override { return m_aabb; } +}; \ No newline at end of file diff --git a/src/geometry/sphere.hpp b/src/geometry/sphere.hpp index 1263d6f..cdb5f13 100644 --- a/src/geometry/sphere.hpp +++ b/src/geometry/sphere.hpp @@ -13,8 +13,9 @@ class Sphere : public IHittable { Point3 m_center; double m_radius; - std::shared_ptr m_material; + AABB m_aabb; + std::shared_ptr m_material; public: diff --git a/src/main.cpp b/src/main.cpp index 6b28ceb..b19f20f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "scenes/sparsed_spheres_scene.hpp" #include "scenes/checkered_spheres_scene.hpp" #include "scenes/solar_system_scene.hpp" +#include "scenes/quads_scene.hpp" #include "renderer/camera.hpp" #include "export/png_exporter.hpp" @@ -28,7 +29,7 @@ int main(int argc, char *argv[]){ unique_ptr scene; - switch(3){ + switch(4){ case 1: scene = make_unique(); break; @@ -38,6 +39,9 @@ int main(int argc, char *argv[]){ case 3: scene = make_unique(); break; + case 4: + scene = make_unique(); + break; default: cout << "Problem in scene selection" << endl; return 1; diff --git a/src/scenes/quads_scene.cpp b/src/scenes/quads_scene.cpp new file mode 100644 index 0000000..baadc49 --- /dev/null +++ b/src/scenes/quads_scene.cpp @@ -0,0 +1,79 @@ + +#include "quads_scene.hpp" + +#include "geometry/hittable_list.hpp" +#include "geometry/quad.hpp" +#include "material/lambertian.hpp" +#include "renderer/camera.hpp" +#include "renderer/pathtracing_renderer.hpp" + +#include + + +using namespace std; + + +shared_ptr QuadsScene::InitCamera() +{ + CameraParams camera_params; + camera_params.aspect_ratio = 1.0; + camera_params.image_width = m_params.render_width; + camera_params.vfov = 80.0; + camera_params.lookfrom = Point3(0,0,9); + camera_params.lookat = Point3(0,0,0); + camera_params.vup = Vec3(0,1,0); + camera_params.defocus_angle = 0.0; + camera_params.focus_dist = 10.0; + + return make_shared(std::move(camera_params)); +} + + +shared_ptr QuadsScene::InitObjects() +{ + auto hittable_list = make_shared(); + + // Materials + auto left_red = make_shared(RGBColor(1.0, 0.2, 0.2)); + auto back_green = make_shared(RGBColor(0.2, 1.0, 0.2)); + auto right_blue = make_shared(RGBColor(0.2, 0.2, 1.0)); + auto upper_orange = make_shared(RGBColor(1.0, 0.5, 0.0)); + auto lower_teal = make_shared(RGBColor(0.2, 0.8, 0.8)); + + // Quads + hittable_list->AddObjects({ + make_shared(Point3(-3,-2, 5), Vec3(0, 0,-4), Vec3(0, 4, 0), left_red), + make_shared(Point3(-2,-2, 0), Vec3(4, 0, 0), Vec3(0, 4, 0), back_green), + make_shared(Point3( 3,-2, 1), Vec3(0, 0, 4), Vec3(0, 4, 0), right_blue), + make_shared(Point3(-2, 3, 1), Vec3(4, 0, 0), Vec3(0, 0, 4), upper_orange), + make_shared(Point3(-2,-3, 5), Vec3(4, 0, 0), Vec3(0, 0,-4), lower_teal) + }); + + return hittable_list; +} + + +shared_ptr QuadsScene::InitRenderer() +{ + PathTracingRendererParams params; + params.aa_sample_per_pixel = 100; + params.max_depth = 20; + + return make_shared(m_camera, m_objets, move(params)); +} + + +void QuadsScene::Build(SceneParams &¶ms) +{ + m_params = params; + m_camera = InitCamera(); + m_objets = InitObjects(); + m_renderer = InitRenderer(); +} + + +shared_ptr QuadsScene::Render() +{ + m_renderer->Render(); + return m_renderer->GetBuffer(); +} diff --git a/src/scenes/quads_scene.hpp b/src/scenes/quads_scene.hpp new file mode 100644 index 0000000..3179643 --- /dev/null +++ b/src/scenes/quads_scene.hpp @@ -0,0 +1,25 @@ + +#pragma once + +#include "scenes/IScene.hpp" + + +class Camera; +class HittableList; +class PathTracingRenderer; + +class QuadsScene: public IScene { + +private: + + std::shared_ptr InitCamera(); + std::shared_ptr InitObjects(); + std::shared_ptr InitRenderer(); + + +public: + + void Build(SceneParams&& params) override; + std::shared_ptr Render() override; + +}; \ No newline at end of file diff --git a/src/scenes/solar_system_scene.cpp b/src/scenes/solar_system_scene.cpp index 01c3bb0..f6326e0 100644 --- a/src/scenes/solar_system_scene.cpp +++ b/src/scenes/solar_system_scene.cpp @@ -1,7 +1,6 @@ #include "solar_system_scene.hpp" -#include "geometry/hittable_list.hpp" #include "geometry/hittable_list.hpp" #include "geometry/sphere.hpp" #include "material/lambertian.hpp" From 4f3c0e3d693be080ed30bc58b0d96435d9ddf441 Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Sun, 1 Sep 2024 19:40:30 +0200 Subject: [PATCH 3/8] add emissive materials and cornell box scene --- TODO.md | 3 +- src/main.cpp | 6 +- src/material/IMaterial.hpp | 6 ++ src/material/diffuse_light.hpp | 27 +++++++++ src/math/vec.hpp | 4 +- src/renderer/camera.hpp | 3 +- src/renderer/pathtracing_renderer.cpp | 31 +++++----- src/renderer/pathtracing_renderer.hpp | 1 + src/scenes/checkered_spheres_scene.cpp | 1 + src/scenes/cornell_box_scene.cpp | 81 ++++++++++++++++++++++++++ src/scenes/cornell_box_scene.hpp | 25 ++++++++ src/scenes/quads_scene.cpp | 1 + src/scenes/solar_system_scene.cpp | 1 + src/scenes/sparsed_spheres_scene.cpp | 1 + 14 files changed, 173 insertions(+), 18 deletions(-) create mode 100644 src/material/diffuse_light.hpp create mode 100644 src/scenes/cornell_box_scene.cpp create mode 100644 src/scenes/cornell_box_scene.hpp diff --git a/TODO.md b/TODO.md index c39fad5..5979742 100644 --- a/TODO.md +++ b/TODO.md @@ -5,4 +5,5 @@ - centralize asset loading in a resource manager - find a good name for the project - have a format describing scenes instead of code description -- add log system \ No newline at end of file +- add log system +- add render queue \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b19f20f..7bc8aa7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "scenes/checkered_spheres_scene.hpp" #include "scenes/solar_system_scene.hpp" #include "scenes/quads_scene.hpp" +#include "scenes/cornell_box_scene.hpp" #include "renderer/camera.hpp" #include "export/png_exporter.hpp" @@ -29,7 +30,7 @@ int main(int argc, char *argv[]){ unique_ptr scene; - switch(4){ + switch(5){ case 1: scene = make_unique(); break; @@ -42,6 +43,9 @@ int main(int argc, char *argv[]){ case 4: scene = make_unique(); break; + case 5: + scene = make_unique(); + break; default: cout << "Problem in scene selection" << endl; return 1; diff --git a/src/material/IMaterial.hpp b/src/material/IMaterial.hpp index e13d7ab..f692655 100644 --- a/src/material/IMaterial.hpp +++ b/src/material/IMaterial.hpp @@ -13,6 +13,7 @@ class IMaterial { public: virtual ~IMaterial() {} + virtual bool Scatter( const Ray& incoming_ray, const HitRecord& rec, @@ -23,5 +24,10 @@ class IMaterial { return false; } + virtual RGBColor Emitted(double u, double v, const Point3& point) const + { + return BLACK; + } + }; \ No newline at end of file diff --git a/src/material/diffuse_light.hpp b/src/material/diffuse_light.hpp new file mode 100644 index 0000000..2751ad2 --- /dev/null +++ b/src/material/diffuse_light.hpp @@ -0,0 +1,27 @@ + +#pragma once + +#include + +#include "material/IMaterial.hpp" +#include "texture/solid_color_texture.hpp" + + +class DiffuseLight : public IMaterial { + +private: + + std::shared_ptr m_albedo; + + +public: + + DiffuseLight(const RGBColor& albedo): m_albedo{std::make_shared(albedo)} {}; + DiffuseLight(std::shared_ptr albedo): m_albedo{albedo} {}; + + RGBColor Emitted(double u, double v, const Point3& point) const override + { + return m_albedo->GetColor(u, v, point); + } + +}; \ No newline at end of file diff --git a/src/math/vec.hpp b/src/math/vec.hpp index 076c795..2636869 100644 --- a/src/math/vec.hpp +++ b/src/math/vec.hpp @@ -106,4 +106,6 @@ inline Vec3 operator*(const Vec3& u, const Vec3& v) { return Vec3{u.e[0]*v.e[0], typedef Vec3 Point3; -typedef Vec3 RGBColor; \ No newline at end of file +typedef Vec3 RGBColor; +inline const RGBColor BLACK = RGBColor(0.0, 0.0, 0.0); +inline const RGBColor WHITE = RGBColor(1.0, 1.0, 1.0); \ No newline at end of file diff --git a/src/renderer/camera.hpp b/src/renderer/camera.hpp index 213315e..6dc10b1 100644 --- a/src/renderer/camera.hpp +++ b/src/renderer/camera.hpp @@ -53,7 +53,8 @@ class Camera { double m_defocus_angle; double m_focus_dist; - Vec3 m_defocus_disk_u; // Defocus disk horizontal radius + // Defocus disk horizontal radius + Vec3 m_defocus_disk_u; Vec3 m_defocus_disk_v; diff --git a/src/renderer/pathtracing_renderer.cpp b/src/renderer/pathtracing_renderer.cpp index ca7acb7..21747f5 100644 --- a/src/renderer/pathtracing_renderer.cpp +++ b/src/renderer/pathtracing_renderer.cpp @@ -91,22 +91,25 @@ void PathTracingRenderer::Render() { RGBColor PathTracingRenderer::GetRayColor(const Ray& ray, size_t depth) { - if(depth == 0){ - return RGBColor(0, 0, 0); + if(depth <= 0){ + return BLACK; } - HitRecord hitRecord; - Interval interval = Interval(0.001, INFINITY); - if( m_scene->Hit(ray, interval, hitRecord) ){ - Ray scattered_ray; - RGBColor attenuation(0, 0, 0); - if (hitRecord.material->Scatter(ray, hitRecord, attenuation, scattered_ray)){ - return attenuation * GetRayColor(scattered_ray, depth-1); - } - return RGBColor(0, 0, 0); + HitRecord hit_record; + static Interval interval = Interval(0.001, INFINITY); + if(!m_scene->Hit(ray, interval, hit_record)){ + return m_params.background_color; } - Vec3 unitDirection = ray.Direction().Normalized(); - double a = 0.5 * (unitDirection[1] + 1.0); - return lerp(RGBColor(1.0, 1.0, 1.0), RGBColor(0.5, 0.7, 1.0), a); + Ray scattered_ray; + RGBColor attenuation = BLACK; + RGBColor color_from_emission = hit_record.material->Emitted(hit_record.u, hit_record.v, hit_record.hit_point); + + if (!hit_record.material->Scatter(ray, hit_record, attenuation, scattered_ray)){ + return color_from_emission; + } + + RGBColor color_from_scatter = attenuation * GetRayColor(scattered_ray, depth-1); + + return color_from_emission + color_from_scatter; } \ No newline at end of file diff --git a/src/renderer/pathtracing_renderer.hpp b/src/renderer/pathtracing_renderer.hpp index 5529ae4..be86902 100644 --- a/src/renderer/pathtracing_renderer.hpp +++ b/src/renderer/pathtracing_renderer.hpp @@ -12,6 +12,7 @@ class Ray; struct PathTracingRendererParams { int aa_sample_per_pixel; int max_depth; + RGBColor background_color; }; diff --git a/src/scenes/checkered_spheres_scene.cpp b/src/scenes/checkered_spheres_scene.cpp index f300bfa..060f15e 100644 --- a/src/scenes/checkered_spheres_scene.cpp +++ b/src/scenes/checkered_spheres_scene.cpp @@ -58,6 +58,7 @@ shared_ptr CheckeredSpheresScene::InitRenderer() PathTracingRendererParams params; params.aa_sample_per_pixel = 100; params.max_depth = 20; + params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); } diff --git a/src/scenes/cornell_box_scene.cpp b/src/scenes/cornell_box_scene.cpp new file mode 100644 index 0000000..0978b5b --- /dev/null +++ b/src/scenes/cornell_box_scene.cpp @@ -0,0 +1,81 @@ + +#include "cornell_box_scene.hpp" + +#include "geometry/hittable_list.hpp" +#include "geometry/hittable_list.hpp" +#include "geometry/quad.hpp" +#include "material/lambertian.hpp" +#include "material/diffuse_light.hpp" +#include "texture/checker_texture.hpp" +#include "renderer/camera.hpp" +#include "renderer/pathtracing_renderer.hpp" + +#include + + +using namespace std; + + +shared_ptr CornellBoxScene::InitCamera() +{ + CameraParams camera_params; + camera_params.aspect_ratio = 1.0; + camera_params.image_width = m_params.render_width; + camera_params.vfov = 40.0; + camera_params.lookfrom = Point3(278, 278, -800); + camera_params.lookat = Point3(278, 278, 0); + camera_params.vup = Vec3(0,1,0); + camera_params.defocus_angle = 0.0; + camera_params.focus_dist = 10.0; + + return make_shared(std::move(camera_params)); +} + + +shared_ptr CornellBoxScene::InitObjects() +{ + auto hittable_list = make_shared(); + + auto red = make_shared(RGBColor(.65, .05, .05)); + auto white = make_shared(RGBColor(.73, .73, .73)); + auto green = make_shared(RGBColor(.12, .45, .15)); + auto light = make_shared(RGBColor(15, 15, 15)); + + hittable_list->AddObjects({ + make_shared(Point3(555,0,0), Vec3(0,555,0), Vec3(0,0,555), green), + make_shared(Point3(0,0,0), Vec3(0,555,0), Vec3(0,0,555), red), + make_shared(Point3(343, 554, 332), Vec3(-130,0,0), Vec3(0,0,-105), light), + make_shared(Point3(0,0,0), Vec3(555,0,0), Vec3(0,0,555), white), + make_shared(Point3(555,555,555), Vec3(-555,0,0), Vec3(0,0,-555), white), + make_shared(Point3(0,0,555), Vec3(555,0,0), Vec3(0,555,0), white) + }); + + return hittable_list; +} + + +shared_ptr CornellBoxScene::InitRenderer() +{ + PathTracingRendererParams params; + params.aa_sample_per_pixel = 1600; + params.max_depth = 20; + params.background_color = BLACK; + + return make_shared(m_camera, m_objets, move(params)); +} + + +void CornellBoxScene::Build(SceneParams &¶ms) +{ + m_params = params; + m_camera = InitCamera(); + m_objets = InitObjects(); + m_renderer = InitRenderer(); +} + + +shared_ptr CornellBoxScene::Render() +{ + m_renderer->Render(); + return m_renderer->GetBuffer(); +} diff --git a/src/scenes/cornell_box_scene.hpp b/src/scenes/cornell_box_scene.hpp new file mode 100644 index 0000000..ad9362b --- /dev/null +++ b/src/scenes/cornell_box_scene.hpp @@ -0,0 +1,25 @@ + +#pragma once + +#include "scenes/IScene.hpp" + + +class Camera; +class HittableList; +class PathTracingRenderer; + +class CornellBoxScene: public IScene { + +private: + + std::shared_ptr InitCamera(); + std::shared_ptr InitObjects(); + std::shared_ptr InitRenderer(); + + +public: + + void Build(SceneParams&& params) override; + std::shared_ptr Render() override; + +}; \ No newline at end of file diff --git a/src/scenes/quads_scene.cpp b/src/scenes/quads_scene.cpp index baadc49..f9ff179 100644 --- a/src/scenes/quads_scene.cpp +++ b/src/scenes/quads_scene.cpp @@ -58,6 +58,7 @@ shared_ptr QuadsScene::InitRenderer() PathTracingRendererParams params; params.aa_sample_per_pixel = 100; params.max_depth = 20; + params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); } diff --git a/src/scenes/solar_system_scene.cpp b/src/scenes/solar_system_scene.cpp index f6326e0..192e3ac 100644 --- a/src/scenes/solar_system_scene.cpp +++ b/src/scenes/solar_system_scene.cpp @@ -75,6 +75,7 @@ shared_ptr SolarSystemScene::InitRenderer() PathTracingRendererParams params; params.aa_sample_per_pixel = 300; params.max_depth = 50; + params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); } diff --git a/src/scenes/sparsed_spheres_scene.cpp b/src/scenes/sparsed_spheres_scene.cpp index b8e300c..faf61dd 100644 --- a/src/scenes/sparsed_spheres_scene.cpp +++ b/src/scenes/sparsed_spheres_scene.cpp @@ -105,6 +105,7 @@ shared_ptr SparsedSpheresScene::InitRenderer() PathTracingRendererParams params; params.aa_sample_per_pixel = 100; params.max_depth = 20; + params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); } From 0adc8de683f644fefa567ddfa044c2976f0b635e Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Mon, 2 Sep 2024 23:09:39 +0200 Subject: [PATCH 4/8] add logging system --- Makefile | 4 +-- TODO.md | 3 +- src/assets/image_asset.cpp | 13 ++++---- src/export/png_exporter.cpp | 4 +-- src/export/ppm_exporter.cpp | 4 +-- src/logger.cpp | 35 +++++++++++++++++++ src/logger.hpp | 48 +++++++++++++++++++++++++++ src/main.cpp | 15 +++++---- src/math/math_utils.cpp | 18 ---------- src/math/math_utils.hpp | 4 --- src/renderer/pathtracing_renderer.cpp | 21 +++++------- src/utils.cpp | 4 +-- 12 files changed, 115 insertions(+), 58 deletions(-) create mode 100644 src/logger.cpp create mode 100644 src/logger.hpp diff --git a/Makefile b/Makefile index 604b2c7..9707de2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CXX = g++ RM = rm -f -CXXFLAGS = -O3 -Wall -Wpedantic -std=c++17 -MMD -MP -fopenmp +CXXFLAGS = -O3 -Wall -Wpedantic -std=c++20 -MMD -MP -fopenmp EXEC = render.exe OUTPUT_DIR = output @@ -37,7 +37,7 @@ $(EXEC): $(OBJS_LOCATION) $(BUILD_OBJS_DIR)/%.o: %.cpp Makefile @$(eval CURRENT_TARGET=$(shell expr $(CURRENT_TARGET) + 1)) - @printf "\rCompiling file $(CURRENT_TARGET) / $(NB_TARGETS)" + @printf "\rCompiling file $(CURRENT_TARGET) / $(NB_TARGETS) " @if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi @$(CXX) $(CXXFLAGS) -I $(SRC_DIR) -c $< -o $@ diff --git a/TODO.md b/TODO.md index 5979742..1b021bb 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,8 @@ -- Book 2 section 4 : texture mapping +- Book 2 section 8 : instances - make buildchain crossplatform with CMake - test to replace RNG for grid sampling in antialiasing - centralize asset loading in a resource manager - find a good name for the project - have a format describing scenes instead of code description -- add log system - add render queue \ No newline at end of file diff --git a/src/assets/image_asset.cpp b/src/assets/image_asset.cpp index a0113b5..4873bc7 100644 --- a/src/assets/image_asset.cpp +++ b/src/assets/image_asset.cpp @@ -2,6 +2,7 @@ #include "image_asset.hpp" #include "utils.hpp" +#include "logger.hpp" #define STB_IMAGE_IMPLEMENTATION #include "third_party/stb_image.h" @@ -17,11 +18,11 @@ namespace fs = std::filesystem; int ImageAsset::Load() { - clog << "Loading " << m_filepath << " ..." << endl; - fs::path path(m_filepath); + Logger::LogInfo("Loading " + m_filepath + " ..."); + fs::path path(m_filepath); if(!fs::exists(m_filepath)){ - cerr << "\t" << m_filepath << ": file not found" << endl; + Logger::LogError("\t" + m_filepath + ": file not found"); return false; } @@ -30,8 +31,8 @@ int ImageAsset::Load() float* fdata; fdata = stbi_loadf(path.c_str(), &m_width, &m_height, &n, m_bytes_per_pixel); if(fdata == NULL){ - cerr << "\t" << m_filepath << ": error while loading file" << endl; - cerr << "\t" << stbi_failure_reason() << endl; + Logger::LogError("\t" + m_filepath + ": error while loading file"); + Logger::LogError("\t" + string(stbi_failure_reason())); return false; } @@ -45,7 +46,7 @@ int ImageAsset::Load() m_bdata[i] = rgb_normalized_to_8bits(m_fdata[i]); } - clog << "Loaded " << m_filepath << " successfully" << endl; + Logger::LogInfo("Loaded " + m_filepath + " successfully"); return true; } diff --git a/src/export/png_exporter.cpp b/src/export/png_exporter.cpp index 471ac58..3101946 100644 --- a/src/export/png_exporter.cpp +++ b/src/export/png_exporter.cpp @@ -2,11 +2,11 @@ #include "png_exporter.hpp" #include "utils.hpp" +#include "logger.hpp" #include #include #include -#include using namespace std; @@ -220,7 +220,7 @@ int PngExporter::Export(int width, int height, shared_ptr buffer) m_output_fs = ofstream(m_filepath, std::ios::out | std::ios::binary); if ( !m_output_fs.is_open()) { - cerr << __FUNCTION__ << " : failed to open " << m_filepath << endl; + Logger::LogError(string(__FUNCTION__) + " : failed to open " + m_filepath); return 1; } diff --git a/src/export/ppm_exporter.cpp b/src/export/ppm_exporter.cpp index 19cc959..eaf1363 100644 --- a/src/export/ppm_exporter.cpp +++ b/src/export/ppm_exporter.cpp @@ -3,9 +3,9 @@ #include "renderer/camera.hpp" #include "math/interval.hpp" #include "utils.hpp" +#include "logger.hpp" #include -#include #include @@ -23,7 +23,7 @@ int PpmExporter::Export(int width, int height, std::shared_ptr buffe ofstream file(m_filepath); if ( !file.is_open()) { - cerr << __FUNCTION__ << " : failed to open " << m_filepath << endl; + Logger::LogError(string(__FUNCTION__) + " : failed to open " + m_filepath); return 1; } diff --git a/src/logger.cpp b/src/logger.cpp new file mode 100644 index 0000000..8754e5e --- /dev/null +++ b/src/logger.cpp @@ -0,0 +1,35 @@ + +#include "logger.hpp" + +#include +#include +#include + + +using namespace std; +using namespace std::chrono; + + +string Logger::GetCurrentTimeFormatted() +{ + auto now = std::chrono::system_clock::now(); + return format("[{:%T}]", zoned_time{ current_zone(), floor(now)}); +} + + +void Logger::Log(const std::string &log, const LogLevel& level) +{ + if(level < s_level){ + return; + } + + ostringstream string_builder; + string_builder << GetCurrentTimeFormatted() << " "; + string_builder << s_colored_name_lookup.at(level) << " "; + string_builder << log << endl; + + const string& formatted_log = string_builder.str(); + for(ostream* stream : s_outputs){ + *stream << formatted_log; + } +} diff --git a/src/logger.hpp b/src/logger.hpp new file mode 100644 index 0000000..9bbcb42 --- /dev/null +++ b/src/logger.hpp @@ -0,0 +1,48 @@ + +#pragma once + +#include +#include + + +enum class LogLevel { + DEBUG = 1, + INFO = 2, + WARNING = 3, + ERROR = 4, + FATAL = 5 +}; + + +class Logger { + +private: + + static inline std::vector s_outputs = { &std::cout }; + static inline LogLevel s_level = LogLevel::DEBUG; + + static inline const std::unordered_map s_colored_name_lookup + { + { LogLevel::DEBUG, "[\x1b[94mDEBUG\x1b[0m] " }, + { LogLevel::INFO, "[INFO] " }, + { LogLevel::WARNING, "[\x1b[93mWARNING\x1b[0m]" }, + { LogLevel::ERROR, "[\x1b[91mERROR\x1b[0m] " }, + { LogLevel::FATAL, "[\x1b[31mFATAL\x1b[0m] " } + }; + + static void Log(const std::string& log, const LogLevel& level); + static std::string GetCurrentTimeFormatted(); + + +public: + + static void SetLogLevel(const LogLevel& level) { s_level = level; } + static void AddOutput(std::ostream& stream) { s_outputs.push_back(&stream); } + + static void LogDebug(const std::string& log) { Log(log, LogLevel::DEBUG); } + static void LogInfo(const std::string& log) { Log(log, LogLevel::INFO); } + static void LogWarning(const std::string& log) { Log(log, LogLevel::WARNING); } + static void LogError(const std::string& log) { Log(log, LogLevel::ERROR); } + static void LogFatal(const std::string& log) { Log(log, LogLevel::FATAL); } + +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7bc8aa7..e16336b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,8 +7,9 @@ #include "scenes/cornell_box_scene.hpp" #include "renderer/camera.hpp" #include "export/png_exporter.hpp" +#include "logger.hpp" -#include +#include #include @@ -18,11 +19,11 @@ using namespace std; int main(int argc, char *argv[]){ if (argc != 2){ - cout << "Usage : " << argv[0] << " width" << endl; + Logger::LogError(format("Usage : {} width", argv[1])); return 1; } - cout << "Initializing scene" << endl; + Logger::LogInfo("Initializing scene"); SceneParams scene_params; scene_params.render_width = atoi(argv[1]); @@ -30,7 +31,7 @@ int main(int argc, char *argv[]){ unique_ptr scene; - switch(5){ + switch(3){ case 1: scene = make_unique(); break; @@ -47,14 +48,14 @@ int main(int argc, char *argv[]){ scene = make_unique(); break; default: - cout << "Problem in scene selection" << endl; + Logger::LogFatal("Problem in scene selection"); return 1; } - cout << "Building scene " << typeid(*scene.get()).name() << endl; + Logger::LogInfo("Building scene " + string(typeid(*scene.get()).name())); scene->Build(std::move(scene_params)); - cout << "Starting rendering" << endl; + Logger::LogInfo("Starting rendering"); shared_ptr color_buffer = scene->Render(); PngExporter png_exporter("output/render.png"); diff --git a/src/math/math_utils.cpp b/src/math/math_utils.cpp index 4ba0483..c936344 100644 --- a/src/math/math_utils.cpp +++ b/src/math/math_utils.cpp @@ -6,24 +6,6 @@ #include -int lerp(int start, int stop, double value) -{ - return int((1-value) * start + value * stop); -} - - -double lerp(double start, double stop, double value) -{ - return (1-value) * start + value * stop; -} - - -Vec3 lerp(const Vec3& start, const Vec3& stop, double value) -{ - return start * (1-value) + stop * value; -} - - double degrees_to_radians(double degrees) { return degrees * M_PI / 180.0; diff --git a/src/math/math_utils.hpp b/src/math/math_utils.hpp index 9590da6..fdef486 100644 --- a/src/math/math_utils.hpp +++ b/src/math/math_utils.hpp @@ -4,10 +4,6 @@ class Vec3; - -int lerp(int start, int stop, double value); -double lerp(double start, double stop, double value); -Vec3 lerp(const Vec3& start, const Vec3& stop, double value); double degrees_to_radians(double degrees); double random_double(); double random_double(double min, double max); diff --git a/src/renderer/pathtracing_renderer.cpp b/src/renderer/pathtracing_renderer.cpp index 21747f5..aeb896f 100644 --- a/src/renderer/pathtracing_renderer.cpp +++ b/src/renderer/pathtracing_renderer.cpp @@ -8,10 +8,11 @@ #include "geometry/hittable_list.hpp" #include "material/IMaterial.hpp" #include "utils.hpp" +#include "logger.hpp" #include -#include #include +#include using namespace std; @@ -43,11 +44,11 @@ void PathTracingRenderer::Render() { } catch (const std::exception& e){ // keep default value - cout << "OMP_NUM_THREAD is undefined" << endl; + Logger::LogWarning("OMP_NUM_THREAD is undefined"); } omp_set_num_threads(num_threads); - cout << "Using " << num_threads << " CPU threads to render" << endl; + Logger::LogInfo(format("Using {} CPU threads to render", num_threads)); int progress = 0; #pragma omp parallel for num_threads(num_threads) shared(progress) @@ -58,10 +59,11 @@ void PathTracingRenderer::Render() { #ifdef _OPENMP #pragma omp critical { - clog << "\rLines remaining: " << (height - progress) << ' ' << flush; + Logger::LogInfo(format("Lines remaining: {} ", height - progress)); + ++progress; } #else - clog << "\rLines remaining: " << (height - j) << ' ' << flush; + Logger::LogInfo(format("Lines remaining: {} ", height - j)); #endif for (int i = 0; i < width; i++) { @@ -76,16 +78,9 @@ void PathTracingRenderer::Render() { m_buffer[j * width + i] = accumulator; } - - #ifdef _OPENMP - #pragma omp critical - { - ++progress; - } - #endif } - clog << "\rDone. \n"; + Logger::LogInfo("Done"); } diff --git a/src/utils.cpp b/src/utils.cpp index 0088dba..95d37c8 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,8 +2,8 @@ #include "utils.hpp" #include "math/interval.hpp" +#include "logger.hpp" -#include #include @@ -17,7 +17,7 @@ string get_env_var(const string& key) { char* val = getenv(key.c_str()); if(val == NULL){ - clog << "Could not retrieve environment variable with key '" << key << "'" << endl; + Logger::LogError("Could not retrieve environment variable with key '" + key + "'"); } return val == NULL ? string("") : string(val); } From 3faa2c6334abb176e2323e560778e885d7e054db Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Mon, 2 Sep 2024 23:56:41 +0200 Subject: [PATCH 5/8] add logger overwrite and progress bar for rendering --- src/logger.cpp | 3 ++- src/logger.hpp | 3 +++ src/main.cpp | 2 +- src/renderer/pathtracing_renderer.cpp | 21 +++++++++---------- src/utils.cpp | 29 ++++++++++++++++++++++++++- src/utils.hpp | 2 ++ 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/logger.cpp b/src/logger.cpp index 8754e5e..d2b12e6 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -26,7 +26,8 @@ void Logger::Log(const std::string &log, const LogLevel& level) ostringstream string_builder; string_builder << GetCurrentTimeFormatted() << " "; string_builder << s_colored_name_lookup.at(level) << " "; - string_builder << log << endl; + string_builder << log; + string_builder << (s_overwrite ? '\r' : '\n'); const string& formatted_log = string_builder.str(); for(ostream* stream : s_outputs){ diff --git a/src/logger.hpp b/src/logger.hpp index 9bbcb42..41070f1 100644 --- a/src/logger.hpp +++ b/src/logger.hpp @@ -1,6 +1,7 @@ #pragma once +#include #include #include @@ -20,6 +21,7 @@ class Logger { static inline std::vector s_outputs = { &std::cout }; static inline LogLevel s_level = LogLevel::DEBUG; + static inline bool s_overwrite = false; static inline const std::unordered_map s_colored_name_lookup { @@ -38,6 +40,7 @@ class Logger { static void SetLogLevel(const LogLevel& level) { s_level = level; } static void AddOutput(std::ostream& stream) { s_outputs.push_back(&stream); } + static void SetOverwrite(bool value) { s_overwrite = value; } static void LogDebug(const std::string& log) { Log(log, LogLevel::DEBUG); } static void LogInfo(const std::string& log) { Log(log, LogLevel::INFO); } diff --git a/src/main.cpp b/src/main.cpp index e16336b..8cced75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,7 @@ using namespace std; int main(int argc, char *argv[]){ if (argc != 2){ - Logger::LogError(format("Usage : {} width", argv[1])); + Logger::LogError(format("Usage : {} width", argv[0])); return 1; } diff --git a/src/renderer/pathtracing_renderer.cpp b/src/renderer/pathtracing_renderer.cpp index aeb896f..334a4f4 100644 --- a/src/renderer/pathtracing_renderer.cpp +++ b/src/renderer/pathtracing_renderer.cpp @@ -34,6 +34,8 @@ void PathTracingRenderer::Render() { const int height = m_camera->ImageHeight(); const int width = m_camera->ImageWidth(); + int progress = 0; + const int bar_width = 70; #ifdef _OPENMP // assuming 6-8 physical cores on machine @@ -50,21 +52,16 @@ void PathTracingRenderer::Render() { omp_set_num_threads(num_threads); Logger::LogInfo(format("Using {} CPU threads to render", num_threads)); - int progress = 0; - #pragma omp parallel for num_threads(num_threads) shared(progress) + #pragma omp parallel for num_threads(num_threads) shared(progress) #endif for (int j = 0; j < height; j++) { - #ifdef _OPENMP - #pragma omp critical - { - Logger::LogInfo(format("Lines remaining: {} ", height - progress)); - ++progress; - } - #else - Logger::LogInfo(format("Lines remaining: {} ", height - j)); - #endif + #pragma omp critical + { + log_progress_bar(progress, height, bar_width, false); + ++progress; + } for (int i = 0; i < width; i++) { @@ -80,6 +77,8 @@ void PathTracingRenderer::Render() { } } + // for satisfaction of full bar + log_progress_bar(progress, height, bar_width, true); Logger::LogInfo("Done"); } diff --git a/src/utils.cpp b/src/utils.cpp index 95d37c8..2030437 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -5,6 +5,8 @@ #include "logger.hpp" #include +#include +#include using namespace std; @@ -43,4 +45,29 @@ void rgb_normalized_to_8bits(const RGBColor& color, uint8_t *dest){ uint8_t rgb_normalized_to_8bits(float value){ return static_cast(255.999 * std::clamp(value, 0.f, 1.f)); -} \ No newline at end of file +} + + +void log_progress_bar(int progress, int total, int bar_width, bool is_last) +{ + Logger::SetOverwrite(true); + + stringstream string_builder; + + float progress_ratio = float(progress)/total; + int pos = bar_width * progress_ratio; + + string_builder << format("[{}/{}] [", progress, total); + for (int i = 0; i < bar_width; ++i) { + if (i < pos) string_builder << "="; + else if (i == pos) string_builder << "-"; + else string_builder << "_"; + } + string_builder << format("] {:.2f} %", progress_ratio*100); + + if(is_last) { + Logger::SetOverwrite(false); + } + + Logger::LogInfo(string_builder.str()); +} diff --git a/src/utils.hpp b/src/utils.hpp index 0e16188..52bdcda 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -15,4 +15,6 @@ void rgb_normalized_to_8bits(const RGBColor& color, uint8_t *dest); uint8_t rgb_normalized_to_8bits(float value); +void log_progress_bar(int progress, int total, int bar_width, bool is_last); + extern float MAGENTA[3]; \ No newline at end of file From 1958031ef8ba5eeaf5bf60e22e2a44efcb9794cd Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Fri, 6 Sep 2024 16:00:21 +0200 Subject: [PATCH 6/8] add iterative rendering, scene class simplification --- src/export/png_exporter.cpp | 2 +- src/export/ppm_exporter.cpp | 2 +- src/logger.cpp | 2 +- src/main.cpp | 7 +- src/renderer/IRenderer.hpp | 3 +- src/renderer/pathtracing_renderer.cpp | 95 +++++++++++++++----------- src/renderer/pathtracing_renderer.hpp | 8 ++- src/scenes/IScene.hpp | 26 +++++-- src/scenes/checkered_spheres_scene.cpp | 20 +----- src/scenes/checkered_spheres_scene.hpp | 13 +--- src/scenes/cornell_box_scene.cpp | 37 +++++----- src/scenes/cornell_box_scene.hpp | 13 +--- src/scenes/quads_scene.cpp | 17 +---- src/scenes/quads_scene.hpp | 9 +-- src/scenes/solar_system_scene.cpp | 20 +----- src/scenes/solar_system_scene.hpp | 9 +-- src/scenes/sparsed_spheres_scene.cpp | 20 +----- src/scenes/sparsed_spheres_scene.hpp | 8 +-- 18 files changed, 126 insertions(+), 185 deletions(-) diff --git a/src/export/png_exporter.cpp b/src/export/png_exporter.cpp index 3101946..bbf9c54 100644 --- a/src/export/png_exporter.cpp +++ b/src/export/png_exporter.cpp @@ -98,7 +98,7 @@ void PngExporter::ImageToScanline(uint8_t filtering, uint8_t *dest) const for(uint32_t j=0; j buffe for(int j=0; j scene; - switch(3){ + switch(5){ case 1: scene = make_unique(); break; @@ -56,7 +57,9 @@ int main(int argc, char *argv[]){ scene->Build(std::move(scene_params)); Logger::LogInfo("Starting rendering"); - shared_ptr color_buffer = scene->Render(); + + auto renderer = dynamic_cast(scene->GetRenderer().get()); + shared_ptr color_buffer = scene->Render(renderer->GetParams().aa_sample_per_pixel); PngExporter png_exporter("output/render.png"); uint32_t out_width = scene->GetCamera()->ImageWidth(); diff --git a/src/renderer/IRenderer.hpp b/src/renderer/IRenderer.hpp index f9d1877..35e758b 100644 --- a/src/renderer/IRenderer.hpp +++ b/src/renderer/IRenderer.hpp @@ -16,7 +16,8 @@ class IRenderer { public: virtual ~IRenderer() {}; - virtual void Render() = 0; + virtual void Init() = 0; + virtual void Render(int n_steps) = 0; virtual std::shared_ptr GetBuffer() = 0; }; \ No newline at end of file diff --git a/src/renderer/pathtracing_renderer.cpp b/src/renderer/pathtracing_renderer.cpp index 334a4f4..061a7f2 100644 --- a/src/renderer/pathtracing_renderer.cpp +++ b/src/renderer/pathtracing_renderer.cpp @@ -12,7 +12,9 @@ #include #include +#include #include +#include "pathtracing_renderer.hpp" using namespace std; @@ -26,61 +28,76 @@ PathTracingRenderer::PathTracingRenderer( : m_camera{camera}, m_scene{scene}, m_params{params} { // shared_ptr initialization with size for array is C++20, we are C++17, workaround - m_buffer = (shared_ptr) make_unique(camera->ImageWidth() * camera->ImageHeight()); + m_buffer = make_shared(camera->ImageWidth() * camera->ImageHeight()); } -void PathTracingRenderer::Render() { +void PathTracingRenderer::Render(int n_steps) { + + bool last_pass = false; + if(n_steps > m_params.aa_sample_per_pixel - m_render_step){ + n_steps = m_params.aa_sample_per_pixel - m_render_step; + last_pass = true; + } + const int height = m_camera->ImageHeight(); const int width = m_camera->ImageWidth(); - int progress = 0; const int bar_width = 70; - - #ifdef _OPENMP - // assuming 6-8 physical cores on machine - int num_threads = 12; - string env_num_threads = get_env_var("OMP_NUM_THREAD"); - try { - num_threads = stoi(env_num_threads); - } - catch (const std::exception& e){ - // keep default value - Logger::LogWarning("OMP_NUM_THREAD is undefined"); + + for(int sample = 0; sample < n_steps; ++sample){ + + log_progress_bar(m_render_step, m_params.aa_sample_per_pixel, bar_width, false); + ++m_render_step; + + #pragma omp parallel for shared(m_buffer, height, width, m_render_step) + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + Ray sampleRay = m_camera->SampleRayForPixel(i, j); + RGBColor ray_color = GetRayColor(sampleRay, m_params.max_depth); + m_buffer[j * width + i] = m_buffer[j * width + i] + (ray_color - m_buffer[j * width + i])/m_render_step; + } } + } + + if(last_pass){ + // for satisfaction of full bar + log_progress_bar(m_render_step, m_params.aa_sample_per_pixel, bar_width, true); + Logger::LogInfo("Done"); + } +} - omp_set_num_threads(num_threads); - Logger::LogInfo(format("Using {} CPU threads to render", num_threads)); - #pragma omp parallel for num_threads(num_threads) shared(progress) +void PathTracingRenderer::Init() +{ + m_render_step = 0; + + #ifdef _OPENMP + SetupOpenMP(); #endif - for (int j = 0; j < height; j++) { + memset((void*) m_buffer.get(), 0, sizeof(m_buffer)); +} - #pragma omp critical - { - log_progress_bar(progress, height, bar_width, false); - ++progress; - } - for (int i = 0; i < width; i++) { - - RGBColor accumulator(0,0,0); - for(int sample = 0; sample < m_params.aa_sample_per_pixel; ++sample){ - Ray sampleRay = m_camera->SampleRayForPixel(i, j); - accumulator += GetRayColor(sampleRay, m_params.max_depth); - } - - accumulator /= m_params.aa_sample_per_pixel; - - m_buffer[j * width + i] = accumulator; - } +#ifdef _OPENMP +void PathTracingRenderer::SetupOpenMP() +{ + // assuming 6-8 physical cores on machine + int num_threads = 12; + string env_num_threads = get_env_var("OMP_NUM_THREAD"); + try { + num_threads = stoi(env_num_threads); } - - // for satisfaction of full bar - log_progress_bar(progress, height, bar_width, true); - Logger::LogInfo("Done"); + catch (const std::exception& e){ + // keep default value + Logger::LogWarning("OMP_NUM_THREAD is undefined"); + } + + omp_set_num_threads(num_threads); + Logger::LogInfo(format("Using {} CPU threads to render", num_threads)); } +#endif RGBColor PathTracingRenderer::GetRayColor(const Ray& ray, size_t depth) diff --git a/src/renderer/pathtracing_renderer.hpp b/src/renderer/pathtracing_renderer.hpp index be86902..72a1970 100644 --- a/src/renderer/pathtracing_renderer.hpp +++ b/src/renderer/pathtracing_renderer.hpp @@ -25,7 +25,11 @@ class PathTracingRenderer : public IRenderer { std::shared_ptr m_buffer; PathTracingRendererParams m_params; + int m_render_step = 0; + #ifdef _OPENMP + void SetupOpenMP(); + #endif public: @@ -35,9 +39,11 @@ class PathTracingRenderer : public IRenderer { PathTracingRendererParams&& params ); - void Render() override; + void Init() override; + void Render(int n_steps) override; RGBColor GetRayColor(const Ray& ray, size_t depth); std::shared_ptr GetBuffer() { return m_buffer; } + PathTracingRendererParams GetParams() { return m_params; } }; \ No newline at end of file diff --git a/src/scenes/IScene.hpp b/src/scenes/IScene.hpp index 60ee0a0..9c47a30 100644 --- a/src/scenes/IScene.hpp +++ b/src/scenes/IScene.hpp @@ -19,20 +19,36 @@ class IRenderer; class IScene { -protected: +protected: SceneParams m_params; std::shared_ptr m_objets; std::shared_ptr m_camera; std::shared_ptr m_renderer; + virtual std::shared_ptr InitCamera() = 0; + virtual std::shared_ptr InitObjects() = 0; + virtual std::shared_ptr InitRenderer() = 0; + public: ~IScene() = default; - virtual void Build(SceneParams&& params) = 0; - virtual std::shared_ptr Render() = 0; - - const Camera* GetCamera() { return m_camera.get(); } + virtual void Build(SceneParams&& params) + { + m_params = params; + m_camera = InitCamera(); + m_objets = InitObjects(); + m_renderer = InitRenderer(); + } + + virtual std::shared_ptr Render(int n_steps) + { + m_renderer->Render(n_steps); + return m_renderer->GetBuffer(); + } + + const std::shared_ptr GetCamera() { return m_camera; } + const std::shared_ptr GetRenderer() { return m_renderer; } }; \ No newline at end of file diff --git a/src/scenes/checkered_spheres_scene.cpp b/src/scenes/checkered_spheres_scene.cpp index 060f15e..76f7032 100644 --- a/src/scenes/checkered_spheres_scene.cpp +++ b/src/scenes/checkered_spheres_scene.cpp @@ -53,7 +53,7 @@ shared_ptr CheckeredSpheresScene::InitObjects() } -shared_ptr CheckeredSpheresScene::InitRenderer() +shared_ptr CheckeredSpheresScene::InitRenderer() { PathTracingRendererParams params; params.aa_sample_per_pixel = 100; @@ -61,20 +61,4 @@ shared_ptr CheckeredSpheresScene::InitRenderer() params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); -} - - -void CheckeredSpheresScene::Build(SceneParams &¶ms) -{ - m_params = params; - m_camera = InitCamera(); - m_objets = InitObjects(); - m_renderer = InitRenderer(); -} - - -shared_ptr CheckeredSpheresScene::Render() -{ - m_renderer->Render(); - return m_renderer->GetBuffer(); -} +} \ No newline at end of file diff --git a/src/scenes/checkered_spheres_scene.hpp b/src/scenes/checkered_spheres_scene.hpp index 9a42ea5..de58183 100644 --- a/src/scenes/checkered_spheres_scene.hpp +++ b/src/scenes/checkered_spheres_scene.hpp @@ -6,20 +6,13 @@ class Camera; class HittableList; -class PathTracingRenderer; class CheckeredSpheresScene: public IScene { private: - std::shared_ptr InitCamera(); - std::shared_ptr InitObjects(); - std::shared_ptr InitRenderer(); - - -public: - - void Build(SceneParams&& params) override; - std::shared_ptr Render() override; + std::shared_ptr InitCamera() override; + std::shared_ptr InitObjects() override; + std::shared_ptr InitRenderer() override; }; \ No newline at end of file diff --git a/src/scenes/cornell_box_scene.cpp b/src/scenes/cornell_box_scene.cpp index 0978b5b..cbeac21 100644 --- a/src/scenes/cornell_box_scene.cpp +++ b/src/scenes/cornell_box_scene.cpp @@ -4,6 +4,7 @@ #include "geometry/hittable_list.hpp" #include "geometry/hittable_list.hpp" #include "geometry/quad.hpp" +#include "geometry/bvh_node.hpp" #include "material/lambertian.hpp" #include "material/diffuse_light.hpp" #include "texture/checker_texture.hpp" @@ -50,32 +51,26 @@ shared_ptr CornellBoxScene::InitObjects() make_shared(Point3(0,0,555), Vec3(555,0,0), Vec3(0,555,0), white) }); + if(m_params.enable_bvh) { + vector> objects = hittable_list->CopyObjects(); + auto root = make_shared(objects, 0, objects.size()); + + hittable_list = make_shared(); + hittable_list->AddObject(root); + } + return hittable_list; } -shared_ptr CornellBoxScene::InitRenderer() +shared_ptr CornellBoxScene::InitRenderer() { PathTracingRendererParams params; - params.aa_sample_per_pixel = 1600; - params.max_depth = 20; + params.aa_sample_per_pixel = 600; + params.max_depth = 10; params.background_color = BLACK; - return make_shared(m_camera, m_objets, move(params)); -} - - -void CornellBoxScene::Build(SceneParams &¶ms) -{ - m_params = params; - m_camera = InitCamera(); - m_objets = InitObjects(); - m_renderer = InitRenderer(); -} - - -shared_ptr CornellBoxScene::Render() -{ - m_renderer->Render(); - return m_renderer->GetBuffer(); -} + m_renderer = make_shared(m_camera, m_objets, move(params)); + m_renderer->Init(); + return m_renderer; +} \ No newline at end of file diff --git a/src/scenes/cornell_box_scene.hpp b/src/scenes/cornell_box_scene.hpp index ad9362b..020129b 100644 --- a/src/scenes/cornell_box_scene.hpp +++ b/src/scenes/cornell_box_scene.hpp @@ -6,20 +6,13 @@ class Camera; class HittableList; -class PathTracingRenderer; class CornellBoxScene: public IScene { private: - std::shared_ptr InitCamera(); - std::shared_ptr InitObjects(); - std::shared_ptr InitRenderer(); - - -public: - - void Build(SceneParams&& params) override; - std::shared_ptr Render() override; + std::shared_ptr InitCamera() override; + std::shared_ptr InitObjects() override; + std::shared_ptr InitRenderer() override; }; \ No newline at end of file diff --git a/src/scenes/quads_scene.cpp b/src/scenes/quads_scene.cpp index f9ff179..3e37d10 100644 --- a/src/scenes/quads_scene.cpp +++ b/src/scenes/quads_scene.cpp @@ -53,7 +53,7 @@ shared_ptr QuadsScene::InitObjects() } -shared_ptr QuadsScene::InitRenderer() +shared_ptr QuadsScene::InitRenderer() { PathTracingRendererParams params; params.aa_sample_per_pixel = 100; @@ -63,18 +63,3 @@ shared_ptr QuadsScene::InitRenderer() return make_shared(m_camera, m_objets, move(params)); } - -void QuadsScene::Build(SceneParams &¶ms) -{ - m_params = params; - m_camera = InitCamera(); - m_objets = InitObjects(); - m_renderer = InitRenderer(); -} - - -shared_ptr QuadsScene::Render() -{ - m_renderer->Render(); - return m_renderer->GetBuffer(); -} diff --git a/src/scenes/quads_scene.hpp b/src/scenes/quads_scene.hpp index 3179643..bf29205 100644 --- a/src/scenes/quads_scene.hpp +++ b/src/scenes/quads_scene.hpp @@ -6,7 +6,6 @@ class Camera; class HittableList; -class PathTracingRenderer; class QuadsScene: public IScene { @@ -14,12 +13,6 @@ class QuadsScene: public IScene { std::shared_ptr InitCamera(); std::shared_ptr InitObjects(); - std::shared_ptr InitRenderer(); - - -public: - - void Build(SceneParams&& params) override; - std::shared_ptr Render() override; + std::shared_ptr InitRenderer(); }; \ No newline at end of file diff --git a/src/scenes/solar_system_scene.cpp b/src/scenes/solar_system_scene.cpp index 192e3ac..1c72b7b 100644 --- a/src/scenes/solar_system_scene.cpp +++ b/src/scenes/solar_system_scene.cpp @@ -70,7 +70,7 @@ shared_ptr SolarSystemScene::InitObjects() } -shared_ptr SolarSystemScene::InitRenderer() +shared_ptr SolarSystemScene::InitRenderer() { PathTracingRendererParams params; params.aa_sample_per_pixel = 300; @@ -78,20 +78,4 @@ shared_ptr SolarSystemScene::InitRenderer() params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); -} - - -void SolarSystemScene::Build(SceneParams &¶ms) -{ - m_params = params; - m_camera = InitCamera(); - m_objets = InitObjects(); - m_renderer = InitRenderer(); -} - - -shared_ptr SolarSystemScene::Render() -{ - m_renderer->Render(); - return m_renderer->GetBuffer(); -} +} \ No newline at end of file diff --git a/src/scenes/solar_system_scene.hpp b/src/scenes/solar_system_scene.hpp index b08f1e5..f6bd121 100644 --- a/src/scenes/solar_system_scene.hpp +++ b/src/scenes/solar_system_scene.hpp @@ -6,7 +6,6 @@ class Camera; class HittableList; -class PathTracingRenderer; class SolarSystemScene: public IScene { @@ -14,12 +13,6 @@ class SolarSystemScene: public IScene { std::shared_ptr InitCamera(); std::shared_ptr InitObjects(); - std::shared_ptr InitRenderer(); - - -public: - - void Build(SceneParams&& params) override; - std::shared_ptr Render() override; + std::shared_ptr InitRenderer(); }; \ No newline at end of file diff --git a/src/scenes/sparsed_spheres_scene.cpp b/src/scenes/sparsed_spheres_scene.cpp index faf61dd..bb140f4 100644 --- a/src/scenes/sparsed_spheres_scene.cpp +++ b/src/scenes/sparsed_spheres_scene.cpp @@ -100,7 +100,7 @@ shared_ptr SparsedSpheresScene::InitObjects() } -shared_ptr SparsedSpheresScene::InitRenderer() +shared_ptr SparsedSpheresScene::InitRenderer() { PathTracingRendererParams params; params.aa_sample_per_pixel = 100; @@ -108,20 +108,4 @@ shared_ptr SparsedSpheresScene::InitRenderer() params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(m_camera, m_objets, move(params)); -} - - -void SparsedSpheresScene::Build(SceneParams &¶ms) -{ - m_params = params; - m_camera = InitCamera(); - m_objets = InitObjects(); - m_renderer = InitRenderer(); -} - - -shared_ptr SparsedSpheresScene::Render() -{ - m_renderer->Render(); - return m_renderer->GetBuffer(); -} +} \ No newline at end of file diff --git a/src/scenes/sparsed_spheres_scene.hpp b/src/scenes/sparsed_spheres_scene.hpp index c2e0265..c400845 100644 --- a/src/scenes/sparsed_spheres_scene.hpp +++ b/src/scenes/sparsed_spheres_scene.hpp @@ -14,12 +14,6 @@ class SparsedSpheresScene: public IScene { std::shared_ptr InitCamera(); std::shared_ptr InitObjects(); - std::shared_ptr InitRenderer(); - - -public: - - void Build(SceneParams&& params) override; - std::shared_ptr Render() override; + std::shared_ptr InitRenderer(); }; \ No newline at end of file From aa75255054998ee8ed915a20ca0fa489736d977e Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Fri, 6 Sep 2024 16:19:10 +0200 Subject: [PATCH 7/8] extract rendering parameters from scene setup, move background_color to camera --- src/main.cpp | 8 +++++- src/renderer/camera.cpp | 35 +++++++++++--------------- src/renderer/camera.hpp | 17 ++++--------- src/renderer/pathtracing_renderer.cpp | 2 +- src/renderer/pathtracing_renderer.hpp | 3 ++- src/scenes/checkered_spheres_scene.cpp | 9 +++---- src/scenes/cornell_box_scene.cpp | 5 +--- src/scenes/quads_scene.cpp | 9 +++---- src/scenes/solar_system_scene.cpp | 9 +++---- src/scenes/sparsed_spheres_scene.cpp | 9 +++---- 10 files changed, 46 insertions(+), 60 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5152ab6..6c3db96 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,8 +58,14 @@ int main(int argc, char *argv[]){ Logger::LogInfo("Starting rendering"); + int sample_per_pixel = 100; + int max_depth = 10; auto renderer = dynamic_cast(scene->GetRenderer().get()); - shared_ptr color_buffer = scene->Render(renderer->GetParams().aa_sample_per_pixel); + PathTracingRendererParams params; + params.aa_sample_per_pixel = sample_per_pixel; + params.max_depth = max_depth; + renderer->SetParams(std::move(params)); + shared_ptr color_buffer = scene->Render(params.aa_sample_per_pixel); PngExporter png_exporter("output/render.png"); uint32_t out_width = scene->GetCamera()->ImageWidth(); diff --git a/src/renderer/camera.cpp b/src/renderer/camera.cpp index f1ea723..83a61f8 100644 --- a/src/renderer/camera.cpp +++ b/src/renderer/camera.cpp @@ -6,40 +6,33 @@ Camera::Camera(CameraParams&& params) { - m_aspect_ratio = params.aspect_ratio; - m_image_width = params.image_width; - m_vfov = params.vfov; - m_lookfrom = params.lookfrom; - m_lookat = params.lookat; - m_vup = params.vup; - m_defocus_angle = params.defocus_angle; - m_focus_dist = params.focus_dist; - - m_camera_center = m_lookfrom; - - m_image_height = int(m_image_width / m_aspect_ratio); + m_params = params; + + m_camera_center = m_params.lookfrom; + + m_image_height = int(m_params.image_width / m_params.aspect_ratio); m_image_height = (m_image_height < 1) ? 1 : m_image_height; - double theta = degrees_to_radians(m_vfov); + double theta = degrees_to_radians(m_params.vfov); double h = tan(theta/2.0); - m_viewport_height = 2.0 * h * m_focus_dist; - m_viewport_width = m_viewport_height * (double(m_image_width) / m_image_height); + m_viewport_height = 2.0 * h * m_params.focus_dist; + m_viewport_width = m_viewport_height * (double(m_params.image_width) / m_image_height); - m_w = (m_lookfrom - m_lookat).Normalized(); - m_u = m_vup.Cross(m_w).Normalized(); + m_w = (m_params.lookfrom - m_params.lookat).Normalized(); + m_u = m_params.vup.Cross(m_w).Normalized(); m_v = m_w.Cross(m_u); m_viewport_u = m_viewport_width * m_u; m_viewport_v = m_viewport_height * (-m_v); - m_pixel_delta_u = m_viewport_u / m_image_width; + m_pixel_delta_u = m_viewport_u / m_params.image_width; m_pixel_delta_v = m_viewport_v / m_image_height; m_viewport_upper_left = m_camera_center - - (m_focus_dist * m_w) - m_viewport_u/2 - m_viewport_v/2; + - (m_params.focus_dist * m_w) - m_viewport_u/2 - m_viewport_v/2; m_pixel00_loc = m_viewport_upper_left + (m_pixel_delta_u + m_pixel_delta_v) * 0.5; - double defocus_radius = m_focus_dist * tan(degrees_to_radians(m_defocus_angle / 2)); + double defocus_radius = m_params.focus_dist * tan(degrees_to_radians(m_params.defocus_angle / 2)); m_defocus_disk_u = m_u * defocus_radius; m_defocus_disk_v = m_v * defocus_radius; } @@ -59,7 +52,7 @@ Ray Camera::SampleRayForPixel(int i, int j) const + offset[0] * m_pixel_delta_u + offset[1] * m_pixel_delta_v; - Point3 ray_origin = (m_defocus_angle <= 0) ? m_camera_center : DefocusDiskSample(); + Point3 ray_origin = (m_params.defocus_angle <= 0) ? m_camera_center : DefocusDiskSample(); return Ray(ray_origin, sample_position - ray_origin);; } diff --git a/src/renderer/camera.hpp b/src/renderer/camera.hpp index 6dc10b1..2de4c14 100644 --- a/src/renderer/camera.hpp +++ b/src/renderer/camera.hpp @@ -16,6 +16,7 @@ struct CameraParams { Vec3 vup; double defocus_angle; double focus_dist; + RGBColor background_color; }; @@ -23,10 +24,10 @@ class Camera { private: + CameraParams m_params; + Vec3 m_camera_center; - double m_aspect_ratio; - int m_image_width; int m_image_height; double m_focal_length; @@ -42,17 +43,8 @@ class Camera { Vec3 m_pixel_delta_v; Point3 m_pixel00_loc; - double m_vfov; - - Point3 m_lookfrom; - Point3 m_lookat; - Vec3 m_vup; - Vec3 m_u, m_v ,m_w; - double m_defocus_angle; - double m_focus_dist; - // Defocus disk horizontal radius Vec3 m_defocus_disk_u; Vec3 m_defocus_disk_v; @@ -63,8 +55,9 @@ class Camera { Camera(CameraParams&& params); double ImageHeight() const { return m_image_height; } - double ImageWidth() const { return m_image_width; } + double ImageWidth() const { return m_params.image_width; } Point3 CameraCenter() const { return m_camera_center; } + CameraParams GetParams() const { return m_params; } Point3 GetPixelPosition(int i, int j) const; diff --git a/src/renderer/pathtracing_renderer.cpp b/src/renderer/pathtracing_renderer.cpp index 061a7f2..191279a 100644 --- a/src/renderer/pathtracing_renderer.cpp +++ b/src/renderer/pathtracing_renderer.cpp @@ -109,7 +109,7 @@ RGBColor PathTracingRenderer::GetRayColor(const Ray& ray, size_t depth) HitRecord hit_record; static Interval interval = Interval(0.001, INFINITY); if(!m_scene->Hit(ray, interval, hit_record)){ - return m_params.background_color; + return m_camera->GetParams().background_color; } Ray scattered_ray; diff --git a/src/renderer/pathtracing_renderer.hpp b/src/renderer/pathtracing_renderer.hpp index 72a1970..155d35f 100644 --- a/src/renderer/pathtracing_renderer.hpp +++ b/src/renderer/pathtracing_renderer.hpp @@ -12,7 +12,6 @@ class Ray; struct PathTracingRendererParams { int aa_sample_per_pixel; int max_depth; - RGBColor background_color; }; @@ -46,4 +45,6 @@ class PathTracingRenderer : public IRenderer { std::shared_ptr GetBuffer() { return m_buffer; } PathTracingRendererParams GetParams() { return m_params; } + void SetParams(PathTracingRendererParams&& params) { m_params = params; } + }; \ No newline at end of file diff --git a/src/scenes/checkered_spheres_scene.cpp b/src/scenes/checkered_spheres_scene.cpp index 76f7032..8e9c6f9 100644 --- a/src/scenes/checkered_spheres_scene.cpp +++ b/src/scenes/checkered_spheres_scene.cpp @@ -26,6 +26,7 @@ shared_ptr CheckeredSpheresScene::InitCamera() camera_params.vup = Vec3(0,1,0); camera_params.defocus_angle = 0.0; camera_params.focus_dist = 10.0; + camera_params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(std::move(camera_params)); } @@ -56,9 +57,7 @@ shared_ptr CheckeredSpheresScene::InitObjects() shared_ptr CheckeredSpheresScene::InitRenderer() { PathTracingRendererParams params; - params.aa_sample_per_pixel = 100; - params.max_depth = 20; - params.background_color = RGBColor(0.70, 0.80, 1.00); - - return make_shared(m_camera, m_objets, move(params)); + m_renderer = make_shared(m_camera, m_objets, move(params)); + m_renderer->Init(); + return m_renderer; } \ No newline at end of file diff --git a/src/scenes/cornell_box_scene.cpp b/src/scenes/cornell_box_scene.cpp index cbeac21..909363d 100644 --- a/src/scenes/cornell_box_scene.cpp +++ b/src/scenes/cornell_box_scene.cpp @@ -28,6 +28,7 @@ shared_ptr CornellBoxScene::InitCamera() camera_params.vup = Vec3(0,1,0); camera_params.defocus_angle = 0.0; camera_params.focus_dist = 10.0; + camera_params.background_color = BLACK; return make_shared(std::move(camera_params)); } @@ -66,10 +67,6 @@ shared_ptr CornellBoxScene::InitObjects() shared_ptr CornellBoxScene::InitRenderer() { PathTracingRendererParams params; - params.aa_sample_per_pixel = 600; - params.max_depth = 10; - params.background_color = BLACK; - m_renderer = make_shared(m_camera, m_objets, move(params)); m_renderer->Init(); return m_renderer; diff --git a/src/scenes/quads_scene.cpp b/src/scenes/quads_scene.cpp index 3e37d10..c28ce56 100644 --- a/src/scenes/quads_scene.cpp +++ b/src/scenes/quads_scene.cpp @@ -24,6 +24,7 @@ shared_ptr QuadsScene::InitCamera() camera_params.vup = Vec3(0,1,0); camera_params.defocus_angle = 0.0; camera_params.focus_dist = 10.0; + camera_params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(std::move(camera_params)); } @@ -56,10 +57,8 @@ shared_ptr QuadsScene::InitObjects() shared_ptr QuadsScene::InitRenderer() { PathTracingRendererParams params; - params.aa_sample_per_pixel = 100; - params.max_depth = 20; - params.background_color = RGBColor(0.70, 0.80, 1.00); - - return make_shared(m_camera, m_objets, move(params)); + m_renderer = make_shared(m_camera, m_objets, move(params)); + m_renderer->Init(); + return m_renderer; } diff --git a/src/scenes/solar_system_scene.cpp b/src/scenes/solar_system_scene.cpp index 1c72b7b..a4d9c44 100644 --- a/src/scenes/solar_system_scene.cpp +++ b/src/scenes/solar_system_scene.cpp @@ -26,6 +26,7 @@ shared_ptr SolarSystemScene::InitCamera() camera_params.vup = Vec3(0,1,0); camera_params.defocus_angle = 0.0; camera_params.focus_dist = 10.0; + camera_params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(std::move(camera_params)); } @@ -73,9 +74,7 @@ shared_ptr SolarSystemScene::InitObjects() shared_ptr SolarSystemScene::InitRenderer() { PathTracingRendererParams params; - params.aa_sample_per_pixel = 300; - params.max_depth = 50; - params.background_color = RGBColor(0.70, 0.80, 1.00); - - return make_shared(m_camera, m_objets, move(params)); + m_renderer = make_shared(m_camera, m_objets, move(params)); + m_renderer->Init(); + return m_renderer; } \ No newline at end of file diff --git a/src/scenes/sparsed_spheres_scene.cpp b/src/scenes/sparsed_spheres_scene.cpp index bb140f4..e18ff18 100644 --- a/src/scenes/sparsed_spheres_scene.cpp +++ b/src/scenes/sparsed_spheres_scene.cpp @@ -25,6 +25,7 @@ shared_ptr SparsedSpheresScene::InitCamera() camera_params.vup = Vec3(0,1,0); camera_params.defocus_angle = 0.6; camera_params.focus_dist = 10.0; + camera_params.background_color = RGBColor(0.70, 0.80, 1.00); return make_shared(std::move(camera_params)); } @@ -103,9 +104,7 @@ shared_ptr SparsedSpheresScene::InitObjects() shared_ptr SparsedSpheresScene::InitRenderer() { PathTracingRendererParams params; - params.aa_sample_per_pixel = 100; - params.max_depth = 20; - params.background_color = RGBColor(0.70, 0.80, 1.00); - - return make_shared(m_camera, m_objets, move(params)); + m_renderer = make_shared(m_camera, m_objets, move(params)); + m_renderer->Init(); + return m_renderer; } \ No newline at end of file From 08f16bfdd784443f8dc5ae03995dbe90a39c3be9 Mon Sep 17 00:00:00 2001 From: PoneyUHC Date: Fri, 6 Sep 2024 17:05:09 +0200 Subject: [PATCH 8/8] add cli options --- run.bash | 2 +- src/main.cpp | 45 ++++++++++++++++++-------- src/scenes/checkered_spheres_scene.cpp | 2 ++ src/scenes/cornell_box_scene.cpp | 2 ++ src/scenes/quads_scene.cpp | 2 ++ src/scenes/solar_system_scene.cpp | 2 ++ src/scenes/sparsed_spheres_scene.cpp | 2 ++ 7 files changed, 43 insertions(+), 14 deletions(-) diff --git a/run.bash b/run.bash index 44b833e..7e46723 100755 --- a/run.bash +++ b/run.bash @@ -7,7 +7,7 @@ if [ "$result" -ne "0" ]; then fi source ./config.bash -./build/executable/render.exe $1 +./build/executable/render.exe $1 $2 $3 $4 result=$? if [ "$result" -eq "0" ]; then diff --git a/src/main.cpp b/src/main.cpp index 6c3db96..6ff11d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,20 +19,37 @@ using namespace std; int main(int argc, char *argv[]){ - if (argc != 2){ - Logger::LogError(format("Usage : {} width", argv[0])); + if (argc != 5){ + Logger::LogError(format("Usage : {} width aa_sample_per_pixel ray_max_depth scene_id", argv[0])); + Logger::LogInfo("Advised values are width=1280 aa_sample_per_pixel=100 ray_max_depth=10 scene_id=5"); return 1; } Logger::LogInfo("Initializing scene"); - + SceneParams scene_params; - scene_params.render_width = atoi(argv[1]); - scene_params.enable_bvh = true; + int aa_sample_per_pixel; + int max_depth; + int scene_id; + + try{ + scene_params.render_width = stoi(argv[1]); + scene_params.enable_bvh = true; + + aa_sample_per_pixel = stoi(argv[2]); + max_depth = stoi(argv[3]); + scene_id = stoi(argv[4]); + } + catch(std::exception const& e) { + Logger::LogFatal("Could not parse command-line arguments"); + Logger::LogFatal(e.what()); + return 1; + } + unique_ptr scene; - switch(5){ + switch(scene_id){ case 1: scene = make_unique(); break; @@ -56,20 +73,22 @@ int main(int argc, char *argv[]){ Logger::LogInfo("Building scene " + string(typeid(*scene.get()).name())); scene->Build(std::move(scene_params)); - Logger::LogInfo("Starting rendering"); - - int sample_per_pixel = 100; - int max_depth = 10; + Logger::LogInfo(format("Starting rendering scene {}", scene_id)); + Logger::LogInfo(format("Using {} samples per pixel, {} max rebounds", aa_sample_per_pixel, max_depth)); + uint32_t out_width = scene->GetCamera()->ImageWidth(); + uint32_t out_height = scene->GetCamera()->ImageHeight(); + Logger::LogInfo(format("Outputing image of size {}x{} pixels", out_width, out_height)); + auto renderer = dynamic_cast(scene->GetRenderer().get()); PathTracingRendererParams params; - params.aa_sample_per_pixel = sample_per_pixel; + params.aa_sample_per_pixel = aa_sample_per_pixel; params.max_depth = max_depth; renderer->SetParams(std::move(params)); + shared_ptr color_buffer = scene->Render(params.aa_sample_per_pixel); PngExporter png_exporter("output/render.png"); - uint32_t out_width = scene->GetCamera()->ImageWidth(); - uint32_t out_height = scene->GetCamera()->ImageHeight(); png_exporter.Export(out_width, out_height, color_buffer); + return 0; } \ No newline at end of file diff --git a/src/scenes/checkered_spheres_scene.cpp b/src/scenes/checkered_spheres_scene.cpp index 8e9c6f9..cb8685c 100644 --- a/src/scenes/checkered_spheres_scene.cpp +++ b/src/scenes/checkered_spheres_scene.cpp @@ -57,6 +57,8 @@ shared_ptr CheckeredSpheresScene::InitObjects() shared_ptr CheckeredSpheresScene::InitRenderer() { PathTracingRendererParams params; + params.aa_sample_per_pixel = 100; + params.max_depth = 10; m_renderer = make_shared(m_camera, m_objets, move(params)); m_renderer->Init(); return m_renderer; diff --git a/src/scenes/cornell_box_scene.cpp b/src/scenes/cornell_box_scene.cpp index 909363d..3b3148d 100644 --- a/src/scenes/cornell_box_scene.cpp +++ b/src/scenes/cornell_box_scene.cpp @@ -67,6 +67,8 @@ shared_ptr CornellBoxScene::InitObjects() shared_ptr CornellBoxScene::InitRenderer() { PathTracingRendererParams params; + params.aa_sample_per_pixel = 100; + params.max_depth = 10; m_renderer = make_shared(m_camera, m_objets, move(params)); m_renderer->Init(); return m_renderer; diff --git a/src/scenes/quads_scene.cpp b/src/scenes/quads_scene.cpp index c28ce56..2b5a0c3 100644 --- a/src/scenes/quads_scene.cpp +++ b/src/scenes/quads_scene.cpp @@ -57,6 +57,8 @@ shared_ptr QuadsScene::InitObjects() shared_ptr QuadsScene::InitRenderer() { PathTracingRendererParams params; + params.aa_sample_per_pixel = 100; + params.max_depth = 10; m_renderer = make_shared(m_camera, m_objets, move(params)); m_renderer->Init(); return m_renderer; diff --git a/src/scenes/solar_system_scene.cpp b/src/scenes/solar_system_scene.cpp index a4d9c44..8053a03 100644 --- a/src/scenes/solar_system_scene.cpp +++ b/src/scenes/solar_system_scene.cpp @@ -74,6 +74,8 @@ shared_ptr SolarSystemScene::InitObjects() shared_ptr SolarSystemScene::InitRenderer() { PathTracingRendererParams params; + params.aa_sample_per_pixel = 100; + params.max_depth = 10; m_renderer = make_shared(m_camera, m_objets, move(params)); m_renderer->Init(); return m_renderer; diff --git a/src/scenes/sparsed_spheres_scene.cpp b/src/scenes/sparsed_spheres_scene.cpp index e18ff18..4814eb2 100644 --- a/src/scenes/sparsed_spheres_scene.cpp +++ b/src/scenes/sparsed_spheres_scene.cpp @@ -104,6 +104,8 @@ shared_ptr SparsedSpheresScene::InitObjects() shared_ptr SparsedSpheresScene::InitRenderer() { PathTracingRendererParams params; + params.aa_sample_per_pixel = 100; + params.max_depth = 10; m_renderer = make_shared(m_camera, m_objets, move(params)); m_renderer->Init(); return m_renderer;