From e46e1c4033b9d96325de3295eb442a5b1fa19f19 Mon Sep 17 00:00:00 2001 From: Keuin Date: Wed, 13 Apr 2022 23:31:47 +0800 Subject: Global diffuse lighting. (gamma not corrected) Some operations on pixel. Make ray3 support copy semantic. Fix vec3 operands does not filter out vec3-vec3 as parameters. random_uv_gen generating random unit vectors. --- hitlist.h | 85 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 31 deletions(-) (limited to 'hitlist.h') diff --git a/hitlist.h b/hitlist.h index 0c65e1a..9b02819 100644 --- a/hitlist.h +++ b/hitlist.h @@ -18,6 +18,9 @@ #include #include +//#define T_SIMPLE_COLOR +//#define T_NORM_VISUAL +#define T_DIFFUSE // A world, T is color depth template @@ -35,40 +38,60 @@ public: } // Given a ray, compute the color. - pixel color(const ray3d &r) const { - // Detect hits - bool hit = false; - double hit_t = std::numeric_limits::infinity(); - std::shared_ptr hit_obj; - // Check the nearest object we hit - for (const auto &obj: objects) { - double t_; - if (obj->hit(r, t_, 0.0) && t_ < hit_t) { - hit = true; - hit_t = t_; - hit_obj = obj; + pixel color(ray3d r, random_uv_gen_3d &ruvg, uint_fast32_t max_recursion_depth = 64) const { + double decay = 1; + while (max_recursion_depth-- > 0) { + // Detect hits + bool hit = false; + double hit_t = std::numeric_limits::infinity(); + std::shared_ptr hit_obj; + // Check the nearest object we hit + for (const auto &obj: objects) { + double t_; + if (obj->hit(r, t_, 0.0) && t_ < hit_t) { + hit = true; + hit_t = t_; + hit_obj = obj; + } + } + if (hit) { +#ifdef T_SIMPLE_COLOR + // simply returns color of the object + return hit_obj->color(); +#endif +#ifdef T_NORM_VISUAL + // normal vector on hit point + const auto nv = hit_obj->normal_vector(r.at(hit_t)); + // visualize normal vector at hit point + return pixel::from_normalized(nv); +#endif +#ifdef T_DIFFUSE + const auto hit_point = r.at(hit_t); // hit point, on the surface + auto nv = hit_obj->normal_vector(hit_point); + if (dot(nv, r.direction()) > 0) return pixel::black(); // discard rays from inner (or invert nv) + vec3d diffuse_target = hit_point + nv + ruvg(); + decay *= 0.5; // lose 50% light when diffused + r = ray3d{hit_point, diffuse_target - hit_point}; // the new diffused ray we trace on + continue; +#endif } - } - if (hit) { - // normal vector on hit point - const auto nv = hit_obj->normal_vector(r.at(hit_t)); -// return obj->color(); - // visualize normal vector at hit point - return pixel::from_normalized(nv); - } - - // Does not hit anything. Get background color (infinity) - const auto u = (r.direction().y + 1.0) * 0.5; - return mix( - pixel::from_normalized(1.0, 1.0, 1.0), - pixel::from_normalized(0.5, 0.7, 1.0), - 1.0 - u, - u - ); + // Does not hit anything. Get background color (infinity) + const auto u = (r.direction().y + 1.0) * 0.5; + const auto c = mix( + pixel::from_normalized(1.0, 1.0, 1.0), + pixel::from_normalized(0.5, 0.7, 1.0), + 1.0 - u, + u + ); +#ifdef T_DIFFUSE + return decay * c; +#else + return c; +#endif + } + return pixel::black(); // reached recursion time limit, very little light } - - }; using hitlist8b = hitlist; -- cgit v1.2.3