summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-15 14:06:27 +0800
committerKeuin <[email protected]>2022-04-15 14:06:27 +0800
commit2d4671d5469116b05709bb1acb614d784d339964 (patch)
treeafa839deea5e01ab3cd062968eae30ca56310370
parent50cd8dd3dd029ce432f8e517b4c054e75b5cfe8e (diff)
Make ray3::decay_ distinguishable between different color channels.
-rw-r--r--bitmap.h5
-rw-r--r--hitlist.h2
-rw-r--r--material.cpp25
-rw-r--r--material.h9
-rw-r--r--ray.h10
-rw-r--r--vec.h13
6 files changed, 50 insertions, 14 deletions
diff --git a/bitmap.h b/bitmap.h
index 64f69a6..a544b03 100644
--- a/bitmap.h
+++ b/bitmap.h
@@ -123,6 +123,11 @@ pixel<T> operator*(S scale, const pixel <T> &pixel) {
return ::pixel < T > {.r=(T) (pixel.r * scale), .g=(T) (pixel.g * scale), .b=(T) (pixel.b * scale)};
}
+template<typename S, typename T>
+pixel<T> operator*(const vec3<S> &scale, const pixel <T> &pixel) {
+ return ::pixel < T > {.r=(T) (pixel.r * scale.x), .g=(T) (pixel.g * scale.y), .b=(T) (pixel.b * scale.z)};
+}
+
// Mix two colors a and b. Returns a*u + b*v
template<typename T>
inline pixel<T> mix(const pixel<T> &a, const pixel<T> &b, double u, double v) {
diff --git a/hitlist.h b/hitlist.h
index 3b853de..797644a 100644
--- a/hitlist.h
+++ b/hitlist.h
@@ -39,7 +39,7 @@ public:
// Given a ray, compute the color.
template<typename T>
pixel<T> color(ray3d r, random_uv_gen_3d &ruvg, uint_fast32_t max_recursion_depth = 64) const {
- assert(r.decay() == 1.0);
+ assert(r.decay().is_one());
while (max_recursion_depth-- > 0) {
// Detect hits
bool hit = false;
diff --git a/material.cpp b/material.cpp
index f92b02c..b312246 100644
--- a/material.cpp
+++ b/material.cpp
@@ -18,16 +18,21 @@ bool material_diffuse_lambertian::scatter(ray3d &r, const object &hit_obj, doubl
return true;
}
-material_diffuse_lambertian::material_diffuse_lambertian(double albedo) : albedo(albedo) {
- assert(albedo >= 0);
- assert(albedo <= 1);
+material_diffuse_lambertian::material_diffuse_lambertian(vec3d albedo) : albedo(albedo) {
+ assert(albedo.mod2() >= 0);
+ assert(albedo.mod2() <= 1);
}
-material_diffuse_simple::material_diffuse_simple(double albedo) : albedo(albedo) {
+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);
@@ -41,11 +46,16 @@ bool material_diffuse_simple::scatter(ray3d &r, const object &hit_obj, double hi
return true;
}
-material_diffuse_hemispherical::material_diffuse_hemispherical(double albedo) : albedo(albedo) {
+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
@@ -59,3 +69,8 @@ material_diffuse_hemispherical::scatter(ray3d &r, const object &hit_obj, double
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);
+}
diff --git a/material.h b/material.h
index a1d03db..b839cc9 100644
--- a/material.h
+++ b/material.h
@@ -22,24 +22,27 @@ public:
};
class material_diffuse_lambertian : public material {
- double albedo;
+ vec3d albedo;
public:
+ explicit material_diffuse_lambertian(vec3d albedo);
explicit material_diffuse_lambertian(double albedo);
bool scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const override;
};
class material_diffuse_simple : public material {
- double albedo;
+ vec3d albedo;
public:
+ explicit material_diffuse_simple(vec3d albedo);
explicit material_diffuse_simple(double albedo);
bool scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const override;
};
class material_diffuse_hemispherical : public material {
- double albedo;
+ vec3d albedo;
public:
+ explicit material_diffuse_hemispherical(vec3d albedo);
explicit material_diffuse_hemispherical(double albedo);
bool scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const override;
diff --git a/ray.h b/ray.h
index 51a3da1..11baa30 100644
--- a/ray.h
+++ b/ray.h
@@ -13,7 +13,7 @@ template<typename T>
class ray3 {
vec3<T> source_;
vec3<T> direction_; // unit vector
- double decay_; // How much power remaining
+ vec3d decay_; // How much power remaining
public:
~ray3() = default;
@@ -30,7 +30,7 @@ public:
}
ray3(const vec3<T> &source, const vec3<T> &direction) :
- source_(source), direction_(direction.unit_vec()), decay_(1.0) {}
+ source_(source), direction_(direction.unit_vec()), decay_{vec3d::one()} {}
// Get the source point from where the ray emits.
vec3<T> source() const {
@@ -65,11 +65,11 @@ public:
return decay_ * color;
}
- void decay(double a) {
- decay_ *= a;
+ void decay(const vec3d &a) {
+ decay_ = decay_.scale(a);
}
- double decay() const {
+ vec3d decay() const {
return decay_;
}
diff --git a/vec.h b/vec.h
index 5050065..99004d6 100644
--- a/vec.h
+++ b/vec.h
@@ -36,12 +36,20 @@ struct vec3 {
return vec3{0, 0, 0};
}
+ static vec3 one() {
+ return vec3{1, 1, 1};
+ }
+
bool is_zero() const {
#define EPS (1e-8)
return x >= -EPS && y >= -EPS && z >= -EPS && x <= EPS && y <= EPS && z <= EPS;
#undef EPS
}
+ bool is_one() const {
+ return (*this - vec3::one()).is_zero();
+ }
+
vec3 operator+(const vec3 &b) const {
return vec3{.x=x + b.x, .y=y + b.y, .z=z + b.z};
}
@@ -68,6 +76,11 @@ struct vec3 {
return vec3{.x=y * b.z - z * b.y, .y=x * b.z - z * b.x, .z=x * b.y - y * b.x};
}
+ // Multiply with b on every dimension.
+ vec3 scale(const vec3 &b) const {
+ return vec3{.x=x * b.x, .y=y * b.y, .z=z * b.z};
+ }
+
// norm value
double norm(const int level = 2) const {
if (level == 2) {