summaryrefslogtreecommitdiff
path: root/hitlist.h
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-13 23:31:47 +0800
committerKeuin <[email protected]>2022-04-13 23:31:47 +0800
commite46e1c4033b9d96325de3295eb442a5b1fa19f19 (patch)
tree27a3976278b006b9dc862ba9fdd7cde338ce43e4 /hitlist.h
parent25ee3cfafea166f2dd155c07b5d43ba90d5bd994 (diff)
Global diffuse lighting. (gamma not corrected)
Some operations on pixel<T>. Make ray3 support copy semantic. Fix vec3 operands does not filter out vec3-vec3 as parameters. random_uv_gen generating random unit vectors.
Diffstat (limited to 'hitlist.h')
-rw-r--r--hitlist.h85
1 files changed, 54 insertions, 31 deletions
diff --git a/hitlist.h b/hitlist.h
index 0c65e1a..9b02819 100644
--- a/hitlist.h
+++ b/hitlist.h
@@ -18,6 +18,9 @@
#include <iostream>
#include <cstdint>
+//#define T_SIMPLE_COLOR
+//#define T_NORM_VISUAL
+#define T_DIFFUSE
// A world, T is color depth
template<typename T>
@@ -35,40 +38,60 @@ public:
}
// Given a ray, compute the color.
- pixel<T> color(const ray3d &r) const {
- // Detect hits
- bool hit = false;
- double hit_t = std::numeric_limits<double>::infinity();
- std::shared_ptr<object> 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<T> 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<double>::infinity();
+ std::shared_ptr<object> 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<T>::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<T>::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<T>::from_normalized(nv);
- }
-
- // Does not hit anything. Get background color (infinity)
- const auto u = (r.direction().y + 1.0) * 0.5;
- return mix(
- pixel<T>::from_normalized(1.0, 1.0, 1.0),
- pixel<T>::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<T>::from_normalized(1.0, 1.0, 1.0),
+ pixel<T>::from_normalized(0.5, 0.7, 1.0),
+ 1.0 - u,
+ u
+ );
+#ifdef T_DIFFUSE
+ return decay * c;
+#else
+ return c;
+#endif
+ }
+ return pixel<T>::black(); // reached recursion time limit, very little light
}
-
-
};
using hitlist8b = hitlist<uint8_t>;