summaryrefslogtreecommitdiff
path: root/material_diffusive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'material_diffusive.cpp')
-rw-r--r--material_diffusive.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/material_diffusive.cpp b/material_diffusive.cpp
new file mode 100644
index 0000000..b312246
--- /dev/null
+++ b/material_diffusive.cpp
@@ -0,0 +1,76 @@
+//
+// Created by Keuin on 2022/4/15.
+//
+
+#include "material.h"
+
+
+bool material_diffuse_lambertian::scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const {
+ 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 false; // discard rays from inner (or invert nv)
+ auto d = nv + ruvg.normalized();
+ if (d.is_zero()) d = nv;
+ vec3d diffuse_target = hit_point + d;
+ r.decay(albedo); // lose some light when diffused
+ r.source(hit_point);
+ r.direction((diffuse_target - hit_point).unit_vec()); // the new diffused ray we trace on
+ return true;
+}
+
+material_diffuse_lambertian::material_diffuse_lambertian(vec3d albedo) : albedo(albedo) {
+ assert(albedo.mod2() >= 0);
+ assert(albedo.mod2() <= 1);
+}
+
+material_diffuse_lambertian::material_diffuse_lambertian(double albedo) : albedo{albedo, albedo, albedo} {
+ assert(albedo >= 0);
+ assert(albedo <= 1);
+}
+
+material_diffuse_simple::material_diffuse_simple(vec3d albedo) : albedo(albedo) {
+ assert(albedo.mod2() >= 0);
+ assert(albedo.mod2() <= 1);
+}
+
+bool material_diffuse_simple::scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const {
+ 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 false; // discard rays from inner (or invert nv)
+ auto d = nv + ruvg.normalized();
+ if (d.is_zero()) d = nv;
+ vec3d diffuse_target = hit_point + nv + ruvg.range01();
+ r.decay(albedo); // lose some light when diffused
+ r.source(hit_point);
+ r.direction((diffuse_target - hit_point).unit_vec()); // the new diffused ray we trace on
+ return true;
+}
+
+material_diffuse_simple::material_diffuse_simple(double albedo) : albedo{albedo, albedo, albedo} {
+ assert(albedo >= 0);
+ assert(albedo <= 1);
+}
+
+material_diffuse_hemispherical::material_diffuse_hemispherical(vec3d albedo) : albedo(albedo) {
+ assert(albedo.mod2() >= 0);
+ assert(albedo.mod2() <= 1);
+}
+
+bool
+material_diffuse_hemispherical::scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const {
+ 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 false; // discard rays from inner (or invert nv)
+ auto d = nv + ruvg.normalized();
+ if (d.is_zero()) d = nv;
+ vec3d diffuse_target = hit_point + ruvg.hemisphere(nv);
+ r.decay(albedo); // lose some light when diffused
+ r.source(hit_point);
+ r.direction((diffuse_target - hit_point).unit_vec()); // the new diffused ray we trace on
+ return true;
+}
+
+material_diffuse_hemispherical::material_diffuse_hemispherical(double albedo) : albedo{albedo, albedo, albedo} {
+ assert(albedo >= 0);
+ assert(albedo <= 1);
+}