Skip to content

Commit 0301eac

Browse files
authored
refactor(render): increase render modularity (#27)
1 parent 1429cc8 commit 0301eac

File tree

2 files changed

+49
-26
lines changed

2 files changed

+49
-26
lines changed

src/include/Prism/scene/scene.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class PRISM_EXPORT Scene {
6565
private:
6666
Color trace(const Ray& ray, int depth) const;
6767

68+
bool is_in_shadow(const std::unique_ptr<Light>& light, const HitRecord& rec) const;
69+
70+
bool hit_closest(const Ray& ray, double t_min, double t_max, HitRecord& rec) const;
71+
6872
std::vector<std::unique_ptr<Object>> objects_; ///< Collection of objects in the scene
6973
std::vector<std::unique_ptr<Light>> lights_; ///< Collection of light sources in the scene
7074
Color ambient_color_ = Color(0.1, 0.1, 0.1); ///< Ambient color for the scene

src/src/scene/scene.cpp

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -65,52 +65,64 @@ std::filesystem::path generate_filename() {
6565
return "render_fallback.ppm";
6666
}
6767

68-
Color Scene::trace(const Ray& ray, int depth) const {
69-
if (depth <= 0) {
70-
return Color(0, 0, 0); // Base case for recursion, return black color
68+
bool Scene::is_in_shadow(const std::unique_ptr<Light>& light, const HitRecord& rec) const {
69+
double light_distance = (light->position - rec.p).magnitude();
70+
Vector3 light_dir = (light->position - rec.p).normalize();
71+
Ray shadow_ray(rec.p, light_dir);
72+
bool in_shadow = false;
73+
for (const auto& obj_ptr : objects_) {
74+
HitRecord shadow_rec;
75+
if (obj_ptr->hit(shadow_ray, 1e-4, light_distance, shadow_rec)) {
76+
in_shadow = true;
77+
break;
78+
}
7179
}
80+
return in_shadow;
81+
}
7282

73-
HitRecord rec;
83+
bool Scene::hit_closest(const Ray& ray, double t_min, double t_max, HitRecord& rec) const {
7484
bool hit_anything = false;
7585
double closest_t = INFINITY;
7686

7787
for (const auto& object_ptr : objects_) {
7888
HitRecord temp_rec;
79-
if (object_ptr->hit(ray, 0.001, closest_t, temp_rec)) {
89+
if (object_ptr->hit(ray, 1e-4, closest_t, temp_rec)) {
8090
hit_anything = true;
8191
closest_t = temp_rec.t;
8292
rec = temp_rec;
8393
}
8494
}
8595

86-
if (!hit_anything) {
96+
return hit_anything;
97+
}
98+
99+
Color Scene::trace(const Ray& ray, int depth) const {
100+
if (depth <= 0) {
101+
return Color(0, 0, 0); // Base case for recursion, return black color
102+
}
103+
104+
HitRecord rec;
105+
if (!hit_closest(ray, 1e-4, INFINITY, rec)) {
87106
return ambient_color_; // Return ambient color if no hit
88107
}
89108

90109
auto mat = rec.material;
91110

92-
Vector3 view_dir = (ray.origin() - rec.p).normalize();
93-
94111
Color surface_color = mat->ka * ambient_color_;
112+
Vector3 view_dir = (ray.origin() - rec.p).normalize();
95113

96114
for (const auto& light_ptr : lights_) {
97-
Vector3 light_dir = (light_ptr->position - rec.p).normalize();
98-
double light_distance = (light_ptr->position - rec.p).magnitude();
99-
100-
Ray shadow_ray(rec.p, light_dir);
101-
bool in_shadow = false;
102-
for (const auto& obj_ptr : objects_) {
103-
HitRecord shadow_rec;
104-
if (obj_ptr->hit(shadow_ray, 0.001, light_distance, shadow_rec)) {
105-
in_shadow = true;
106-
break;
107-
}
108-
}
115+
if (!is_in_shadow(light_ptr, rec)) {
109116

110-
if (!in_shadow) {
117+
// Diffuse contribution
118+
Vector3 light_dir = (light_ptr->position - rec.p).normalize();
111119
double diff_factor = std::max(rec.normal.dot(light_dir), 0.0);
112120
surface_color += mat->color * diff_factor * light_ptr->color;
113121

122+
// Specular contribution
123+
if (mat->ks.r == 0 && mat->ks.g == 0 && mat->ks.b == 0) {
124+
continue; // Skip specular if ks is black
125+
}
114126
Vector3 reflect_dir = (-light_dir) - rec.normal * 2 * (-light_dir).dot(rec.normal);
115127
double spec_factor = std::pow(std::max(view_dir.dot(reflect_dir), 0.0), mat->ns);
116128
surface_color += mat->ks * spec_factor * light_ptr->color;
@@ -119,6 +131,7 @@ Color Scene::trace(const Ray& ray, int depth) const {
119131

120132
Color final_color = mat->ke + surface_color;
121133

134+
// Handle transparency and refraction
122135
double opacity = mat->d;
123136
if (opacity < 1.0) {
124137
double reflectance;
@@ -138,12 +151,12 @@ Color Scene::trace(const Ray& ray, int depth) const {
138151
Color refraction_color = Color(0, 0, 0);
139152

140153
Vector3 reflect_dir = ray.direction() - rec.normal * 2 * ray.direction().dot(rec.normal);
141-
Ray reflection_ray(rec.p, reflect_dir);
154+
Ray reflection_ray(rec.p + rec.normal * 1e-4, reflect_dir);
142155
reflection_color = trace(reflection_ray, depth - 1);
143156

144157
if (reflectance < 1.0) {
145158
Vector3 refracted_dir = refract(unit_direction, rec.normal, refraction_ratio);
146-
Ray refracted_ray(rec.p, refracted_dir);
159+
Ray refracted_ray(rec.p - rec.normal * 1e-4, refracted_dir);
147160
refraction_color = trace(refracted_ray, depth - 1);
148161
}
149162

@@ -152,8 +165,8 @@ Color Scene::trace(const Ray& ray, int depth) const {
152165
final_color = final_color * opacity + trasmited_color * (1.0 - opacity);
153166
} else if (mat->ks.r > 0 || mat->ks.g > 0 || mat->ks.b > 0) {
154167
Vector3 reflect_dir = ray.direction() - rec.normal * 2 * ray.direction().dot(rec.normal);
155-
Ray reflection_ray(rec.p, reflect_dir);
156-
final_color += mat->ks * trace(reflection_ray, depth - 1);
168+
Ray reflection_ray(rec.p + rec.normal * 1e-4, reflect_dir);
169+
final_color = final_color * (1.0 - mat->ks.r) + mat->ks * trace(reflection_ray, depth - 1);
157170
}
158171

159172
return final_color.clamp();
@@ -176,6 +189,8 @@ void Scene::render() const {
176189
Style::logInfo("Output directory: " + Prism::Style::CYAN + clean_path.string());
177190
Style::logInfo("Starting render...\n");
178191

192+
auto start_time = std::chrono::steady_clock::now();
193+
179194
image_file << "P3\n" << camera_.pixel_width << " " << camera_.pixel_height << "\n255\n";
180195

181196
int total_pixels = camera_.pixel_height * camera_.pixel_width;
@@ -195,11 +210,15 @@ void Scene::render() const {
195210
Style::logStatusBar(static_cast<double>(current_progress_percent) / 100.0);
196211
}
197212
}
198-
199213
image_file.close();
200214

215+
auto end_time = std::chrono::steady_clock::now();
216+
std::chrono::duration<double> elapsed_seconds = end_time - start_time;
217+
201218
Style::logDone("Rendering complete.");
219+
Style::logDone("Total render time: " + Prism::Style::CYAN + std::to_string(elapsed_seconds.count()) + "s");
202220
Style::logDone("Image saved as: " + Prism::Style::CYAN + full_path.string());
221+
203222
}
204223

205224
} // namespace Prism

0 commit comments

Comments
 (0)