33
44#include < iostream>
55
6- #include " hitable .hpp"
6+ #include " hit_record .hpp"
77#include " texture.hpp"
88#include " vec.hpp"
99#include " visit.hpp"
@@ -22,8 +22,7 @@ struct lambertian_material {
2222 scattered = ray (rec.p , scatter_direction, r_in.time ());
2323 // Attenuation of the ray hitting the object is modified based on the color
2424 // at hit point
25- attenuation *=
26- dev_visit ([&](auto && arg) { return arg.value (ctx, rec); }, albedo);
25+ attenuation *= dev_visit (texture_value_visitor (ctx, rec), albedo);
2726 return true ;
2827 }
2928 color emitted (auto &, const hit_record& rec) { return color (0 , 0 , 0 ); }
@@ -77,8 +76,7 @@ struct dielectric_material {
7776 real_t sin_theta = sycl::sqrt (1 .0f - cos_theta * cos_theta);
7877 bool cannot_refract = refraction_ratio * sin_theta > 1 .0f ;
7978 vec direction;
80- if (cannot_refract ||
81- reflectance (cos_theta, refraction_ratio) > rng.real ())
79+ if (cannot_refract || reflectance (cos_theta, refraction_ratio) > rng.real ())
8280 direction = reflect (unit_direction, rec.normal );
8381 else
8482 direction = refract (unit_direction, rec.normal , refraction_ratio);
@@ -104,7 +102,7 @@ struct lightsource_material {
104102 template <typename ... T> bool scatter (T&...) const { return false ; }
105103
106104 color emitted (auto & ctx, const hit_record& rec) {
107- return dev_visit ([&]( auto && arg) { return arg. value ( ctx, rec); } , emit);
105+ return dev_visit (texture_value_visitor ( ctx, rec), emit);
108106 }
109107
110108 texture_t emit;
@@ -120,8 +118,7 @@ struct isotropic_material {
120118 color& attenuation, ray& scattered) const {
121119 auto & rng = ctx.rng ;
122120 scattered = ray (rec.p , rng.in_unit_ball (), r_in.time ());
123- attenuation *=
124- dev_visit ([&](auto && arg) { return arg.value (ctx, rec); }, albedo);
121+ attenuation *= dev_visit (texture_value_visitor (ctx, rec), albedo);
125122 return true ;
126123 }
127124
@@ -131,7 +128,54 @@ struct isotropic_material {
131128};
132129
133130using material_t =
134- std::variant<lambertian_material, metal_material, dielectric_material,
135- lightsource_material, isotropic_material>;
131+ std::variant<std::monostate, lambertian_material, metal_material,
132+ dielectric_material, lightsource_material, isotropic_material>;
133+
134+ struct material_emitted_visitor {
135+ private:
136+ task_context& ctx;
137+ const hit_record& rec;
138+
139+ public:
140+ material_emitted_visitor (task_context& ctx, hit_record& rec)
141+ : ctx { ctx }
142+ , rec { rec } {}
143+
144+ template <typename M> color operator ()(M&& material) {
145+ return material.emitted (ctx, rec);
146+ }
147+
148+ color operator ()(std::monostate) {
149+ assert (false && " unreachable" );
150+ return { 0 .f , 0 .f , 0 .f };
151+ }
152+ };
153+
154+ struct material_scatter_visitor {
155+ private:
156+ task_context& ctx;
157+ const ray& r_in;
158+ const hit_record& rec;
159+ color& attenuation;
160+ ray& scattered;
161+
162+ public:
163+ material_scatter_visitor (auto & ctx, const ray& r_in, const hit_record& rec,
164+ color& attenuation, ray& scattered)
165+ : ctx { ctx }
166+ , r_in { r_in }
167+ , rec { rec }
168+ , attenuation { attenuation }
169+ , scattered { scattered } {}
170+
171+ template <typename M> bool operator ()(M&& material) {
172+ return material.scatter (ctx, r_in, rec, attenuation, scattered);
173+ }
174+
175+ bool operator ()(std::monostate) {
176+ assert (false && " unreachable" );
177+ return false ;
178+ }
179+ };
136180
137181#endif
0 commit comments