Skip to content

Commit

Permalink
#5 29.2 Implementing Textures
Browse files Browse the repository at this point in the history
Add SV_Matte class.
  • Loading branch information
mandyedi committed Nov 26, 2024
1 parent 09cb9e1 commit e36e4b0
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 0 deletions.
163 changes: 163 additions & 0 deletions src/Materials/SV_Matte.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright (C) Kevin Suffern 2000-2007.
// This C++ code is for non-commercial purposes only.
// This C++ code is licensed under the GNU General Public License Version 2.
// See the file COPYING.txt for the full license.

// Copyright notice for changes since the originally published version:
// Copyright (C) Eduárd Mándy 2019-2021
// Though this C++ code was change in a large measure it still has the original copyright notice.
// This C++ code is for non-commercial purposes only.
// This C++ code is licensed under the GNU General Public License Version 2.
// See the file COPYING.txt for the full license.

#include "SV_Matte.h"

#include "../Lights/Light.h"
#include "../Tracers/Tracer.h"

SV_Matte::SV_Matte() : Material(), ambient_brdf(new SV_Lambertian), diffuse_brdf(new SV_Lambertian) {}

SV_Matte::~SV_Matte() {
if (ambient_brdf != nullptr) {
delete ambient_brdf;
ambient_brdf = nullptr;
}

if (diffuse_brdf != nullptr) {
delete diffuse_brdf;
diffuse_brdf = nullptr;
}
}

SV_Matte::SV_Matte(const SV_Matte& m) : Material(m) {
ambient_brdf = m.ambient_brdf->clone();
diffuse_brdf = m.diffuse_brdf->clone();
}

SV_Matte::SV_Matte(SV_Matte&& m) noexcept : Material(std::move(m)) {
ambient_brdf = m.ambient_brdf;
m.ambient_brdf = nullptr;
diffuse_brdf = m.diffuse_brdf;
m.diffuse_brdf = nullptr;
}

SV_Matte& SV_Matte::operator=(const SV_Matte& m) {
Material::operator=(m);

if (ambient_brdf != nullptr) {
delete ambient_brdf;
}
ambient_brdf = m.ambient_brdf->clone();

if (diffuse_brdf != nullptr) {
delete diffuse_brdf;
}
diffuse_brdf = m.diffuse_brdf->clone();

return *this;
}

SV_Matte& SV_Matte::operator=(SV_Matte&& m) noexcept {
Material::operator=(std::move(m));

if (ambient_brdf != nullptr) {
delete ambient_brdf;
}
ambient_brdf = m.ambient_brdf;
m.ambient_brdf = nullptr;

if (diffuse_brdf != nullptr) {
delete diffuse_brdf;
}
diffuse_brdf = m.diffuse_brdf;
m.diffuse_brdf = nullptr;

return *this;
}

Material* SV_Matte::clone() const { return new SV_Matte(*this); }

RGBColor SV_Matte::shade(ShadeRec& sr) {
Vector3D wo = -sr.ray.d;
RGBColor L = ambient_brdf->rho(sr, wo) * sr.w.ambient_ptr->L(sr);
size_t num_lights = sr.w.lights.size();

for (size_t j = 0; j < num_lights; j++) {
Vector3D wi = sr.w.lights[j]->get_direction(sr);
float ndotwi = sr.normal * wi;
float ndotwo = sr.normal * wo;

if (ndotwi > 0.0f && ndotwo > 0.0f) {
bool in_shadow = false;

if (sr.w.lights[j]->casts_shadows()) {
Ray shadowRay(sr.hit_point, wi);
in_shadow = sr.w.lights[j]->in_shadow(shadowRay, sr);
}

if (!in_shadow) {

// TODO: what is sr.w.lights[j]->G and do I need to add it somewhere else?
L += diffuse_brdf->f(sr, wo, wi) * sr.w.lights[j]->L(sr) * sr.w.lights[j]->G(sr) * static_cast<float>(ndotwi);
}
}
}

return L;
}

RGBColor SV_Matte::path_shade(ShadeRec& sr) {
Vector3D wo = -sr.ray.d;
Vector3D wi;
float pdf;
RGBColor f = diffuse_brdf->sample_f(sr, wo, wi, pdf);
float ndotwi = sr.normal * wi;
Ray reflected_ray(sr.hit_point, wi);

return f * sr.w.tracer_ptr->trace_ray(reflected_ray, sr.depth + 1) * ndotwi / pdf;
}

RGBColor SV_Matte::global_shade(ShadeRec& sr) {
RGBColor L;

if (sr.depth == 0) {
L = area_light_shade(sr);
}

Vector3D wi;
Vector3D wo = -sr.ray.d;
float pdf;
RGBColor f = diffuse_brdf->sample_f(sr, wo, wi, pdf);
float ndotwi = sr.normal * wi;
Ray reflected_ray(sr.hit_point, wi);

L += f * sr.w.tracer_ptr->trace_ray(reflected_ray, sr.depth + 1) * ndotwi / pdf;

return L;
}

RGBColor SV_Matte::area_light_shade(ShadeRec& sr) {
Vector3D wo = -sr.ray.d;
RGBColor L = ambient_brdf->rho(sr, wo) * sr.w.ambient_ptr->L(sr);
int num_lights = sr.w.lights.size();

for (int j = 0; j < num_lights; j++) {
Vector3D wi = sr.w.lights[j]->get_direction(sr);
float ndotwi = sr.normal * wi;

if (ndotwi > 0.0f) {
bool in_shadow = false;

if (sr.w.lights[j]->casts_shadows()) {
Ray shadow_ray(sr.hit_point, wi);
in_shadow = sr.w.lights[j]->in_shadow(shadow_ray, sr);
}

if (!in_shadow) {
L += diffuse_brdf->f(sr, wo, wi) * sr.w.lights[j]->L(sr) * sr.w.lights[j]->G(sr) * ndotwi / sr.w.lights[j]->pdf(sr);
}
}
}

return L;
}
71 changes: 71 additions & 0 deletions src/Materials/SV_Matte.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (C) Kevin Suffern 2000-2007.
// This C++ code is for non-commercial purposes only.
// This C++ code is licensed under the GNU General Public License Version 2.
// See the file COPYING.txt for the full license.

// Copyright notice for changes since the originally published version:
// Copyright (C) Eduárd Mándy 2019-2021
// Though this C++ code was change in a large measure it still has the original copyright notice.
// This C++ code is for non-commercial purposes only.
// This C++ code is licensed under the GNU General Public License Version 2.
// See the file COPYING.txt for the full license.

#ifndef __SV_MATTE__
#define __SV_MATTE__

#include "../BRDFs/SV_Lambertian.h"
#include "../Materials/Material.h"

class SV_Matte : public Material {
public:

SV_Matte();

~SV_Matte();

SV_Matte(const SV_Matte& m);

SV_Matte(SV_Matte&& m) noexcept;

SV_Matte& operator=(const SV_Matte& m);

SV_Matte& operator=(SV_Matte&& m) noexcept;

Material* clone() const override;

void set_ka(const float k);

void set_kd(const float k);

void set_cd(const Texture* texture_ptr);

RGBColor shade(ShadeRec& sr) override;

RGBColor path_shade(ShadeRec& sr) override;

RGBColor global_shade(ShadeRec& sr);

RGBColor area_light_shade(ShadeRec& sr) override;

private:

SV_Lambertian* ambient_brdf = nullptr;
SV_Lambertian* diffuse_brdf = nullptr;
};

// this sets Lambertian::kd
// there is no Lambertian::ka data member because ambient reflection
// is diffuse reflection

inline void SV_Matte::set_ka(const float ka) { ambient_brdf->set_kd(ka); }

// this also sets Lambertian::kd, but for a different Lambertian object

inline void SV_Matte::set_kd(const float kd) { diffuse_brdf->set_kd(kd); }

inline void SV_Matte::set_cd(const Texture *texture_ptr) {
ambient_brdf->set_cd(texture_ptr);
diffuse_brdf->set_cd(texture_ptr);
}

#endif

0 comments on commit e36e4b0

Please sign in to comment.