diff options
author | Keuin <[email protected]> | 2022-04-14 19:49:14 +0800 |
---|---|---|
committer | Keuin <[email protected]> | 2022-04-14 20:02:22 +0800 |
commit | ed66f6748c8121aacf6c3cd48b9ac001c85c0978 (patch) | |
tree | adc72ccb8599b5742b141645faf6e03452efb261 | |
parent | 25305140df28c19f622209bb514d290ad6e6486b (diff) |
Implement Lambertian Reflection and Hemispherical Reflection.
-rw-r--r-- | hitlist.h | 15 | ||||
-rw-r--r-- | vec.h | 27 |
2 files changed, 35 insertions, 7 deletions
@@ -22,6 +22,11 @@ //#define T_NORM_VISUAL #define T_DIFFUSE +// Select which diffuse method to use +//#define DIFFUSE_SIMPLE // Diffuse with a random vector whose length is in [0, 1] +#define DIFFUSE_LR // Diffuse with (possibly wrong) Lambertian Reflection, i.e. using a random unit vector +//#define DIFFUSE_HEMI // Diffuse with hemispherical scattering, i.e. using a normalized random vector within the hemisphere + // A world, T is color depth template<typename T> class hitlist { @@ -76,7 +81,15 @@ public: 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<T>::black(); // discard rays from inner (or invert nv) - vec3d diffuse_target = hit_point + nv + ruvg(); +#ifdef DIFFUSE_SIMPLE + vec3d diffuse_target = hit_point + nv + ruvg.range01(); +#endif +#ifdef DIFFUSE_LR + vec3d diffuse_target = hit_point + nv + ruvg.normalized(); +#endif +#ifdef DIFFUSE_HEMI + vec3d diffuse_target = hit_point + ruvg.hemisphere(nv); +#endif decay *= 0.5; // lose 50% light when diffused r = ray3d{hit_point, diffuse_target - hit_point}; // the new diffused ray we trace on continue; @@ -144,23 +144,38 @@ using vec3d = vec3<double>; // random unit vector generator template<typename T> -class random_uv_gen { +class rand_vec_gen { std::mt19937_64 mt; std::uniform_real_distribution<T> uni{-1.0, 1.0}; public: - random_uv_gen() = delete; - explicit random_uv_gen(uint64_t seed) : mt{seed} {} + rand_vec_gen() = delete; - vec3<T> operator()() { + explicit rand_vec_gen(uint64_t seed) : mt{seed} {} + + // Get a random vector whose length is in [0, 1] + inline vec3<T> range01() { while (true) { const auto x = uni(mt), y = uni(mt), z = uni(mt); const auto vec = vec3<T>{.x=x, .y=y, .z=z}; - if (vec.mod2() <= 1.0) return vec; + if (vec.mod2() <= 1.0) return vec.unit_vec(); } } + + // Get a unit vector with random direction. + inline vec3<T> normalized() { + return range01().unit_vec(); + } + + // Get a random vector whose length is in [0, 1] and + // has a direction difference less than 90 degree with given vector. + inline vec3<T> hemisphere(vec3<T> &vec) { + const auto v = range01(); + if (dot(v, vec) > 0) return v; + return -v; + } }; -using random_uv_gen_3d = random_uv_gen<double>; +using random_uv_gen_3d = rand_vec_gen<double>; #endif //RT_VEC_H
\ No newline at end of file |