diff --git a/sprout/darkroom/colors/rgb.hpp b/sprout/darkroom/colors/rgb.hpp index 43cff05e..e944ae8b 100644 --- a/sprout/darkroom/colors/rgb.hpp +++ b/sprout/darkroom/colors/rgb.hpp @@ -117,6 +117,14 @@ namespace sprout { sprout::darkroom::colors::b(lhs) * rhs ); } + template + inline SPROUT_CONSTEXPR Color + mul(Color const& lhs, Fac const& rhs, Tail const&... tail) { + return sprout::darkroom::colors::mul( + sprout::darkroom::colors::mul(lhs, rhs), + tail... + ); + } // // add // @@ -130,6 +138,14 @@ namespace sprout { sprout::darkroom::colors::b(lhs) + sprout::darkroom::colors::b(rhs) ); } + template + inline SPROUT_CONSTEXPR Color1 + add(Color1 const& lhs, Color2 const& rhs, Tail const&... tail) { + return sprout::darkroom::colors::add( + sprout::darkroom::colors::add(lhs, rhs), + tail... + ); + } // // filter // @@ -143,6 +159,14 @@ namespace sprout { sprout::darkroom::colors::b(lhs) * sprout::darkroom::colors::b(rhs) ); } + template + inline SPROUT_CONSTEXPR Color1 + filter(Color1 const& lhs, Color2 const& rhs, Tail const&... tail) { + return sprout::darkroom::colors::filter( + sprout::darkroom::colors::filter(lhs, rhs), + tail... + ); + } // // rgb_f_to_rgb diff --git a/sprout/darkroom/coords/vector.hpp b/sprout/darkroom/coords/vector.hpp index 4568e96e..d4fd0303 100644 --- a/sprout/darkroom/coords/vector.hpp +++ b/sprout/darkroom/coords/vector.hpp @@ -59,6 +59,17 @@ namespace sprout { return sprout::darkroom::coords::vector3d_t(x, y, z); } + // + // is_zero + // + template + inline SPROUT_CONSTEXPR bool + is_zero(Vector const& vec) { + return sprout::darkroom::coords::x(vec) == 0 + && sprout::darkroom::coords::y(vec) == 0 + && sprout::darkroom::coords::z(vec) == 0 + ; + } // // length_sq // @@ -204,6 +215,37 @@ namespace sprout { sprout::darkroom::coords::scale(nor, sprout::darkroom::coords::dot(incid, nor) * 2) ); } + // + // refract + // + namespace detail { + template + inline SPROUT_CONSTEXPR Incident + refract_impl_1(Incident const& incid, Normal const& nor, Refraction const& eta, InNor const& t, K const& k) { + return k < 0 ? sprout::tuples::remake(incid, 0, 0, 0) + : sprout::darkroom::coords::sub( + sprout::darkroom::coords::scale(incid, eta), + sprout::darkroom::coords::scale(nor, eta * t * sprout::sqrt(k)) + ) + ; + } + template + inline SPROUT_CONSTEXPR Incident + refract_impl(Incident const& incid, Normal const& nor, Refraction const& eta, InNor const& t) { + return sprout::darkroom::coords::detail::refract_impl_1( + incid, nor, eta, + t, 1 - eta * eta * (1 - t * t) + ); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR Incident + refract(Incident const& incid, Normal const& nor, Refraction const& eta) { + return sprout::darkroom::coords::detail::refract_impl( + incid, nor, eta, + sprout::darkroom::coords::dot(incid, nor) + ); + } } // namespace coords } // namespace darkroom } // namespace sprout diff --git a/sprout/darkroom/intersects/intersection.hpp b/sprout/darkroom/intersects/intersection.hpp index 0335aa89..2f7100ef 100644 --- a/sprout/darkroom/intersects/intersection.hpp +++ b/sprout/darkroom/intersects/intersection.hpp @@ -8,6 +8,7 @@ #ifndef SPROUT_DARKROOM_INTERSECTS_INTERSECTION_HPP #define SPROUT_DARKROOM_INTERSECTS_INTERSECTION_HPP +#include #include #include #include @@ -89,7 +90,7 @@ namespace sprout { } template< typename T, - typename sprout::enabler_if::value>::type = sprout::enabler + typename sprout::enabler_if::type>::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR auto is_from_inside(T&& t) @@ -100,7 +101,7 @@ namespace sprout { } template< typename T, - typename sprout::enabler_if::value>::type = sprout::enabler + typename sprout::enabler_if::type>::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR typename sprout::darkroom::access::element<5, sprout::darkroom::intersects::intersection>::type is_from_inside(T&&) diff --git a/sprout/darkroom/lights/parallel_light.hpp b/sprout/darkroom/lights/parallel_light.hpp index cab2069a..0d3b6010 100644 --- a/sprout/darkroom/lights/parallel_light.hpp +++ b/sprout/darkroom/lights/parallel_light.hpp @@ -79,14 +79,8 @@ namespace sprout { inter, sprout::darkroom::objects::intersect( objs, - sprout::darkroom::rays::make_ray( - sprout::darkroom::coords::add( - sprout::darkroom::coords::scale( - dir_, - sprout::numeric_limits::epsilon() * 256 - ), - sprout::darkroom::intersects::point_of_intersection(inter) - ), + sprout::darkroom::rays::make_detached_ray( + sprout::darkroom::intersects::point_of_intersection(inter), dir_ ) ) diff --git a/sprout/darkroom/lights/point_light.hpp b/sprout/darkroom/lights/point_light.hpp index e5c20474..e6991736 100644 --- a/sprout/darkroom/lights/point_light.hpp +++ b/sprout/darkroom/lights/point_light.hpp @@ -83,14 +83,8 @@ namespace sprout { direction, sprout::darkroom::objects::intersect( objs, - sprout::darkroom::rays::make_ray( - sprout::darkroom::coords::add( - sprout::darkroom::coords::scale( - direction, - sprout::numeric_limits::epsilon() * 256 - ), - sprout::darkroom::intersects::point_of_intersection(inter) - ), + sprout::darkroom::rays::make_detached_ray( + sprout::darkroom::intersects::point_of_intersection(inter), direction ) ) diff --git a/sprout/darkroom/objects/sphere.hpp b/sprout/darkroom/objects/sphere.hpp index 5e3e18d1..c53ac245 100644 --- a/sprout/darkroom/objects/sphere.hpp +++ b/sprout/darkroom/objects/sphere.hpp @@ -110,12 +110,15 @@ namespace sprout { } template SPROUT_CONSTEXPR typename intersection::type - intersect_6(Ray const& ray, zwo_type const& zwo, drei_type const& drei, Vec const& normal) const { + intersect_6(Ray const& ray, zwo_type const& zwo, drei_type const& drei,bool is_from_inside, Vec const& normal) const { return typename intersection::type( sprout::tuples::get(zwo), sprout::tuples::get(zwo), sprout::tuples::get(drei), - sprout::tuples::get(drei), + is_from_inside + ? sprout::darkroom::coords::negate(normal) + : normal + , sprout::darkroom::materials::calculate_material( // ! Spherical mat_, sprout::atan2( @@ -133,7 +136,7 @@ namespace sprout { ) / sprout::math::half_pi() ), - sprout::darkroom::coords::dot(normal, sprout::darkroom::rays::direction(ray)) > 0 + is_from_inside ); } template @@ -143,6 +146,7 @@ namespace sprout { ray, zwo, drei, + sprout::darkroom::coords::dot(sprout::tuples::get(drei), sprout::darkroom::rays::direction(ray)) > 0, sprout::tuples::get(drei) ); } diff --git a/sprout/darkroom/rays/ray.hpp b/sprout/darkroom/rays/ray.hpp index 01e27802..1bd233c4 100644 --- a/sprout/darkroom/rays/ray.hpp +++ b/sprout/darkroom/rays/ray.hpp @@ -9,6 +9,7 @@ #define SPROUT_DARKROOM_RAYS_RAY_HPP #include +#include #include #include #include @@ -63,6 +64,32 @@ namespace sprout { sprout::darkroom::coords::scale(sprout::darkroom::rays::direction(ray), dist) ); } + + // + // detach_position + // + template + inline SPROUT_CONSTEXPR Position + detach_position(Position const& pos, Direction const& dir) { + return sprout::darkroom::coords::add( + pos, + sprout::darkroom::coords::resize( + dir, + sprout::numeric_limits::type>::epsilon() * 256 + ) + ); + } + // + // make_detached_ray + // + template + inline SPROUT_CONSTEXPR sprout::tuples::tuple + make_detached_ray(Position const& pos, Direction const& dir) { + return sprout::darkroom::rays::make_ray( + sprout::darkroom::rays::detach_position(pos, dir), + dir + ); + } } // namespace rays } // namespace darkroom } // namespace sprout diff --git a/sprout/darkroom/renderers/whitted_style.hpp b/sprout/darkroom/renderers/whitted_style.hpp index bd486246..937dd922 100644 --- a/sprout/darkroom/renderers/whitted_style.hpp +++ b/sprout/darkroom/renderers/whitted_style.hpp @@ -43,7 +43,7 @@ namespace sprout { Camera const& camera, Objects const& objs, Lights const& lights, Ray const& ray, Intersection const& inter, Renderer const& renderer, std::size_t depth_max, - Direction const& reflect_dir + Direction const& new_dir ) const { return sprout::darkroom::renderers::calculate( @@ -51,19 +51,8 @@ namespace sprout { camera, objs, lights, sprout::tuples::remake( ray, - sprout::darkroom::coords::add( - sprout::darkroom::intersects::point_of_intersection(inter), - sprout::darkroom::coords::scale( - reflect_dir, - sprout::numeric_limits::type>::epsilon() * 256 - ) - // ??? -// sprout::darkroom::coords::scale( -// sprout::darkroom::intersects::normal(inter), -// sprout::numeric_limits::type>::epsilon() * 256 -// ) - ), - reflect_dir + sprout::darkroom::rays::detach_position(sprout::darkroom::intersects::point_of_intersection(inter), new_dir), + new_dir ), depth_max - 1 ); @@ -102,6 +91,80 @@ namespace sprout { } }; // + // whitted_transparent + // + class whitted_transparent { + private: + template< + typename Color, + typename Camera, typename Objects, typename Lights, + typename Ray, typename Intersection, typename Renderer, + typename Direction + > + SPROUT_CONSTEXPR Color + color_1( + Camera const& camera, Objects const& objs, Lights const& lights, + Ray const& ray, Intersection const& inter, Renderer const& renderer, + std::size_t depth_max, + Direction const& new_dir + ) const + { + return !sprout::darkroom::coords::is_zero(new_dir) + ? sprout::darkroom::renderers::calculate( + renderer, + camera, objs, lights, + sprout::tuples::remake( + ray, + sprout::darkroom::rays::detach_position(sprout::darkroom::intersects::point_of_intersection(inter), new_dir), + new_dir + ), + depth_max - 1 + ) + : sprout::tuples::make(0, 0, 0) + ; + } + public: + template< + typename Color, + typename Camera, typename Objects, typename Lights, + typename Ray, typename Intersection, typename Renderer + > + SPROUT_CONSTEXPR Color + operator()( + Camera const& camera, Objects const& objs, Lights const& lights, + Ray const& ray, Intersection const& inter, Renderer const& renderer, + std::size_t depth_max + ) const + { + typedef typename std::decay< + decltype(sprout::darkroom::materials::alpha(sprout::darkroom::intersects::material(inter))) + >::type alpha_type; + typedef typename std::decay< + decltype(sprout::darkroom::materials::refraction(sprout::darkroom::intersects::material(inter))) + >::type refraction_type; + return depth_max > 0 + && sprout::darkroom::intersects::does_intersect(inter) + && sprout::darkroom::materials::alpha(sprout::darkroom::intersects::material(inter)) + > sprout::numeric_limits::epsilon() + && sprout::darkroom::materials::refraction(sprout::darkroom::intersects::material(inter)) + > sprout::numeric_limits::epsilon() + ? color_1( + camera, objs, lights, + ray, inter, renderer, + depth_max, + sprout::darkroom::coords::refract( + sprout::darkroom::rays::direction(ray), + sprout::darkroom::intersects::normal(inter), + sprout::darkroom::intersects::is_from_inside(inter) + ? 1 / sprout::darkroom::materials::refraction(sprout::darkroom::intersects::material(inter)) + : sprout::darkroom::materials::refraction(sprout::darkroom::intersects::material(inter)) + ) + ) + : sprout::tuples::make(0, 0, 0) + ; + } + }; + // // whitted_style // template @@ -115,18 +178,24 @@ namespace sprout { SPROUT_CONSTEXPR Color color_3( Ray const& ray, Intersection const& inter, - Color const& diffuse_color, Color const& mirror_color + Color const& diffuse_color, Color const& mirror_color, Color const& transparent_color ) const { return sprout::darkroom::intersects::does_intersect(inter) ? sprout::darkroom::colors::add( sprout::darkroom::colors::mul( diffuse_color, - 1 - sprout::darkroom::materials::reflection(sprout::darkroom::intersects::material(inter)) + 1 + - sprout::darkroom::materials::reflection(sprout::darkroom::intersects::material(inter)) + - sprout::darkroom::materials::alpha(sprout::darkroom::intersects::material(inter)) ), sprout::darkroom::colors::mul( mirror_color, sprout::darkroom::materials::reflection(sprout::darkroom::intersects::material(inter)) + ), + sprout::darkroom::colors::mul( + transparent_color, + sprout::darkroom::materials::alpha(sprout::darkroom::intersects::material(inter)) ) ) : sprout::darkroom::renderers::calculate_infinity(infinity_color_, sprout::darkroom::rays::direction(ray)) @@ -148,6 +217,11 @@ namespace sprout { ray, inter, diffuse_color, sprout::darkroom::renderers::whitted_mirror().template operator()( + camera, objs, lights, + ray, inter, *this, + depth_max + ), + sprout::darkroom::renderers::whitted_transparent().template operator()( camera, objs, lights, ray, inter, *this, depth_max