summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-14 19:49:14 +0800
committerKeuin <[email protected]>2022-04-14 20:02:22 +0800
commited66f6748c8121aacf6c3cd48b9ac001c85c0978 (patch)
treeadc72ccb8599b5742b141645faf6e03452efb261
parent25305140df28c19f622209bb514d290ad6e6486b (diff)
Implement Lambertian Reflection and Hemispherical Reflection.
-rw-r--r--hitlist.h15
-rw-r--r--vec.h27
2 files changed, 35 insertions, 7 deletions
diff --git a/hitlist.h b/hitlist.h
index 10be932..d498b26 100644
--- a/hitlist.h
+++ b/hitlist.h
@@ -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;
diff --git a/vec.h b/vec.h
index 9a29f8b..8efbc9a 100644
--- a/vec.h
+++ b/vec.h
@@ -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