@@ -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 << " \n 255\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