-
Hello, i wanted to implement Phong model for plastic-like material to have an half matte/half glossy look. I' m basing the phong model from these resources here: The model is basically a BRDF summarizable by this image here: in practice there is a usual part of cosine reflection plus another part that takes into account the asymmetrical part of the scattering taking into account the angle between an ideal metallic-like reflectance and the actual reflected ray (alpha in the figures). I' ve tried to implement it by adding some arguments to the usual functions in the project: class PhongPDF : public PDF {
private:
ONB uvw;
double _kd;
double _ks;
int _n;
public:
PhongPDF(const Vec3& w, double kd, double ks, int n) : uvw(w), _kd(kd), _ks(ks), _n(n) {}
double value(
const Vec3& direction_out,
const Vec3& direction_in,
const Vec3& direction_view) const override;
Vec3 generate() const override;
}; // class PhongPDF
double PhongPDF::value(
const Vec3& direction_out,
const Vec3& direction_in,
const Vec3& direction_view) const {
auto cos_theta = dot(unit_vector(direction_out), uvw.w());
auto reflection = std::fmax(0, cos_theta/pi);
auto R = reflect(direction_in, uvw.w());
auto specular = std::pow(dot(-R, -direction_view), _n);
return _ks*specular + _kd*reflection;
}
Vec3 PhongPDF::generate() const {
auto r = random_double();
if (r < _kd) {
return uvw.transform(random_cosine_direction());
} else if (_kd <= r && r < _kd + _ks) {
return uvw.transform(random_phong_direction(_n));
} else {
return Vec3();
}
}
inline Vec3 random_phong_direction(int n) {
auto r1 = random_double();
auto r2 = random_double();
auto phi = 2*pi*r2;
auto r1_1 = std::pow(r1, 2./(1+n));
auto r1_2 = std::pow(r1, 1./(1+n));
auto x = std::cos(phi)*std::sqrt(1-r1_1);
auto y = std::sin(phi)*std::sqrt(1-r1_1);
auto z = r1_2;
return Vec3(x,y,z);
} class Phong : public Material {
private:
std::shared_ptr<Texture> tex;
// kd+ks <= 1
double _kd; // phong model diffuse constant
double _ks; // phong model specular constant
int _n; // phong model exponent
public:
Phong(
std::shared_ptr<Texture> tex,
double kd = 0.2,
double ks = 0.8,
int n = 10) :
tex(tex),
_kd(kd),
_ks(ks),
_n(n) {}
Phong(
const Color& albedo,
double kd = 0.2,
double ks = 0.8,
int n = 10) : Phong(std::make_shared<SolidColor>(albedo), kd, ks, n) {}
void set_n(int n) {_n = n; }
void set_kd(double kd) {
_kd = kd;
_ks = 1. - kd;
}
bool scatter(
const Ray& r_in,
const HitRecord& rec,
scatter_record_t& srec) const override;
double scattering_pdf(
const Ray& r_in,
const HitRecord& rec,
const Ray& scattered,
const Vec3& vdir) const override;
}; // class Phong
bool Phong::scatter(
[[maybe_unused]] const Ray& r_in,
const HitRecord& rec,
scatter_record_t& srec) const {
scattered_rays_t scattered_ray;
scattered_ray.pdf = std::make_shared<PhongPDF>(rec.normal(), _kd, _ks, _n);
scattered_ray.skip_pdf = false;
scattered_ray.attenuation = tex->value(rec.u(), rec.v(), rec.normal());
srec.scattered_rays.push_back(scattered_ray);
return true;
}
double Phong::scattering_pdf(
const Ray& r_in,
const HitRecord& rec,
const Ray& scattered,
const Vec3& vdir) const {
auto cos_theta = dot(rec.normal(), unit_vector(scattered.direction()));
auto reflection = std::fmax(0, cos_theta/pi);
auto R = reflect(r_in.direction(), rec.normal());
auto specular = std::pow(dot(-R, -vdir), _n);
return _ks*specular + _kd*reflection;
} with the due changes in the camera part auto light_ptr = std::make_shared<HittablePDF>(lights, rec.point());
MixturePDF p(light_ptr, ray_t.pdf);
Ray scattered = Ray(rec.point(), p.generate(), r.time());
auto pdf_value = p.value(scattered.direction(), r.direction(), vdir);
double scattering_pdf = rec.material()->scattering_pdf(r,rec,scattered, vdir); // vdir = lookat - lookfrom
Color sample_color = ray_color(scattered, depth-1, world, lights);
color_from_scatter += (ray_t.attenuation * scattering_pdf * sample_color) / pdf_value; I' m obviously doing something wrong since the image i'm getting lokks like If interested the fully executable project is in the phong branch of my repo |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
the error was not due to the model |
Beta Was this translation helpful? Give feedback.
the error was not due to the model