diff options
author | Keuin <[email protected]> | 2022-04-15 14:06:27 +0800 |
---|---|---|
committer | Keuin <[email protected]> | 2022-04-15 14:06:27 +0800 |
commit | 2d4671d5469116b05709bb1acb614d784d339964 (patch) | |
tree | afa839deea5e01ab3cd062968eae30ca56310370 | |
parent | 50cd8dd3dd029ce432f8e517b4c054e75b5cfe8e (diff) |
Make ray3::decay_ distinguishable between different color channels.
-rw-r--r-- | bitmap.h | 5 | ||||
-rw-r--r-- | hitlist.h | 2 | ||||
-rw-r--r-- | material.cpp | 25 | ||||
-rw-r--r-- | material.h | 9 | ||||
-rw-r--r-- | ray.h | 10 | ||||
-rw-r--r-- | vec.h | 13 |
6 files changed, 50 insertions, 14 deletions
@@ -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) { @@ -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); +} @@ -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; @@ -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_; } @@ -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) { |