From 0267419a2fc67e06bdfc13d0a77030b2bad974cd Mon Sep 17 00:00:00 2001 From: Eduard Mandy Date: Fri, 15 Mar 2024 14:41:13 +0100 Subject: [PATCH] #5 Realistic Transparency --- CMakeLists.txt | 4 ++ src/BRDFs/FresnelReflector.cpp | 69 +++++++++++++++++++++++++++ src/BRDFs/FresnelReflector.h | 56 ++++++++++++++++++++++ src/BTDFs/BTDF.h | 2 +- src/BTDFs/FresnelTransmitter.cpp | 81 ++++++++++++++++++++++++++++++++ src/BTDFs/FresnelTransmitter.h | 59 +++++++++++++++++++++++ src/BTDFs/PerfectTransmitter.cpp | 2 +- src/BTDFs/PerfectTransmitter.h | 2 +- src/Materials/Dielectric.cpp | 13 +++++ src/Materials/Dielectric.h | 22 +++++++++ 10 files changed, 307 insertions(+), 3 deletions(-) create mode 100644 src/BRDFs/FresnelReflector.cpp create mode 100644 src/BRDFs/FresnelReflector.h create mode 100644 src/BTDFs/FresnelTransmitter.cpp create mode 100644 src/BTDFs/FresnelTransmitter.h create mode 100644 src/Materials/Dielectric.cpp create mode 100644 src/Materials/Dielectric.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 35ca844..eb61080 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ endif () set (SOURCE_BRDFS src/BRDFs/BRDF.cpp src/BRDFs/BRDF.h + src/BRDFs/FresnelReflector.cpp + src/BRDFs/FresnelReflector.h src/BRDFs/GlossySpecular.cpp src/BRDFs/GlossySpecular.h src/BRDFs/Lambertian.cpp @@ -29,6 +31,8 @@ set (SOURCE_BRDFS set (SOURCE_BTDFS src/BTDFs/BTDF.cpp src/BTDFs/BTDF.h + src/BTDFs/FresnelTransmitter.cpp + src/BTDFs/FresnelTransmitter.h src/BTDFs/PerfectTransmitter.cpp src/BTDFs/PerfectTransmitter.h ) diff --git a/src/BRDFs/FresnelReflector.cpp b/src/BRDFs/FresnelReflector.cpp new file mode 100644 index 0000000..7ea0cad --- /dev/null +++ b/src/BRDFs/FresnelReflector.cpp @@ -0,0 +1,69 @@ +// 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 "FresnelReflector.h" + +#include +#include + +#include "../Utilities/ShadeRec.h" +#include "../Utilities/Vector3D.h" + +FresnelReflector::FresnelReflector(const FresnelReflector& fr) : BRDF(fr), eta_in(fr.eta_in), eta_out(fr.eta_out) {} + +FresnelReflector::FresnelReflector(FresnelReflector&& fr) noexcept : BRDF(std::move(fr)), eta_in(std::exchange(fr.eta_in, 1.0f)), eta_out(std::exchange(fr.eta_out, 1.0f)) {} + +FresnelReflector& FresnelReflector::operator=(const FresnelReflector& fr) { + FresnelReflector::operator=(fr); + eta_in = fr.eta_in; + eta_out = fr.eta_out; + + return *this; +} + +FresnelReflector& FresnelReflector::operator=(FresnelReflector&& fr) noexcept { + FresnelReflector::operator=(fr); + eta_in = std::exchange(fr.eta_in, 1.0f); + eta_out = std::exchange(fr.eta_out, 1.0f); + + return *this; +} + +FresnelReflector* FresnelReflector::clone() const { return new FresnelReflector(*this); } + +RGBColor FresnelReflector::sample_f(const ShadeRec& sr, const Vector3D& wo, Vector3D& wr) const { + float ndotwo = sr.normal * wo; + wr = -wo + 2.0f * sr.normal * ndotwo; + return fresnel(sr) * RGBColor::white / fabs(sr.normal * wr); +} + +float FresnelReflector::fresnel(const ShadeRec& sr) const { + Normal normal(sr.normal); + float ndotd = -normal * sr.ray.d; + float eta; + + if (ndotd < 0.0f) { + normal = -normal; + eta = eta_out / eta_in; + } else { + eta = eta_in / eta_out; + } + + float cos_theta_i = -normal * sr.ray.d; + float temp = 1.0f - (1.0f - cos_theta_i * cos_theta_i) / (eta * eta); + float cos_theta_t = sqrt(1.0f - (1.0f - cos_theta_i * cos_theta_i) / (eta * eta)); + float r_parallel = (eta * cos_theta_i - cos_theta_t) / (eta * cos_theta_i + cos_theta_t); + float r_perpendicular = (cos_theta_i - eta * cos_theta_t) / (cos_theta_i + eta * cos_theta_t); + float kr = 0.5f * (r_parallel * r_parallel + r_perpendicular * r_perpendicular); + + return kr; +} diff --git a/src/BRDFs/FresnelReflector.h b/src/BRDFs/FresnelReflector.h new file mode 100644 index 0000000..f1c3a18 --- /dev/null +++ b/src/BRDFs/FresnelReflector.h @@ -0,0 +1,56 @@ +// 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 __FRESNEL_REFLECTOR__ +#define __FRESNEL_REFLECTOR__ + +class ShadeRec; +class Vector; + +#include "BRDF.h" + +class FresnelReflector : public BRDF { +public: + + FresnelReflector() = default; + + ~FresnelReflector() = default; + + FresnelReflector(const FresnelReflector& fr); + + FresnelReflector(FresnelReflector&& fr) noexcept; + + FresnelReflector& operator=(const FresnelReflector& fr); + + FresnelReflector& operator=(FresnelReflector&& fr) noexcept; + + FresnelReflector* clone() const override; + + void set_eta_in(const float eta); + + void set_eta_out(const float eta); + + RGBColor sample_f(const ShadeRec& sr, const Vector3D& wo, Vector3D& wr) const override; + +private: + + float eta_in = 1.0f; + float eta_out = 1.0f; + + float fresnel(const ShadeRec& sr) const; +}; + +inline void FresnelReflector::set_eta_in(const float eta) { eta_in = eta; } + +inline void FresnelReflector::set_eta_out(const float eta) { eta_out = eta; } + +#endif diff --git a/src/BTDFs/BTDF.h b/src/BTDFs/BTDF.h index 4268343..2549016 100644 --- a/src/BTDFs/BTDF.h +++ b/src/BTDFs/BTDF.h @@ -33,7 +33,7 @@ class BTDF { BTDF& operator=(BTDF&& btdf) = default; - virtual BTDF* clone() = 0; + virtual BTDF* clone() const = 0; virtual RGBColor f(const ShadeRec& sr, const Vector3D& wo, const Vector3D& wi) const; diff --git a/src/BTDFs/FresnelTransmitter.cpp b/src/BTDFs/FresnelTransmitter.cpp new file mode 100644 index 0000000..46d48e5 --- /dev/null +++ b/src/BTDFs/FresnelTransmitter.cpp @@ -0,0 +1,81 @@ +// 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 "FresnelTransmitter.h" + +#include +#include + +#include "../Utilities/Vector3D.h" +#include "../Utilities/ShadeRec.h" + +FresnelTransmitter::FresnelTransmitter(const FresnelTransmitter& pt) : BTDF(pt), kt(pt.kt), ior(pt.ior) {} + +FresnelTransmitter::FresnelTransmitter(FresnelTransmitter&& pt) noexcept : BTDF(std::move(pt)), kt(std::exchange(pt.kt, 0.0f)), ior(std::exchange(pt.ior, 1.0f)) {} + +FresnelTransmitter& FresnelTransmitter::operator=(const FresnelTransmitter& pt) { + FresnelTransmitter::operator=(pt); + kt = pt.kt; + ior = pt.ior; + + return *this; +} + +FresnelTransmitter& FresnelTransmitter::operator=(FresnelTransmitter&& pt) noexcept { + FresnelTransmitter::operator=(pt); + kt = std::exchange(pt.kt, 0.0f); + ior = std::exchange(pt.ior, 1.0f); + + return *this; +} + +FresnelTransmitter* FresnelTransmitter::clone() const { return new FresnelTransmitter(*this); } + +// tests for total internal reflection + +bool FresnelTransmitter::tir(const ShadeRec& sr) const { + Vector3D wo(-sr.ray.d); + float cos_thetai = sr.normal * wo; + float eta = ior; + + if (cos_thetai < 0.0f) { + eta = 1.0f / eta; + } + + return 1.0f - (1.0f - cos_thetai * cos_thetai) / (eta * eta) < 0.0f; +} + +RGBColor FresnelTransmitter::f(const ShadeRec& sr, const Vector3D& wo, const Vector3D& wi) const { return RGBColor::black; } + +// this computes the direction wt for perfect transmission +// and returns the transmission coefficient +// this is only called when there is no total internal reflection + +RGBColor FresnelTransmitter::sample_f(const ShadeRec& sr, const Vector3D& wo, Vector3D& wt) const { + Normal n(sr.normal); + float cos_thetai = n * wo; + float eta = ior; + + if (cos_thetai < 0.0f) { // transmitted ray is outside + cos_thetai = -cos_thetai; + n = -n; // reverse direction of normal + eta = 1.0f / eta; // invert ior + } + + float temp = 1.0f - (1.0f - cos_thetai * cos_thetai) / (eta * eta); + float cos_theta2 = sqrt(temp); + wt = -wo / eta - (cos_theta2 - cos_thetai / eta) * n; + + return kt / (eta * eta) * RGBColor::white / fabs(sr.normal * wt); +} + +RGBColor FresnelTransmitter::rho(const ShadeRec& sr, const Vector3D& wo) const { return RGBColor::black; } diff --git a/src/BTDFs/FresnelTransmitter.h b/src/BTDFs/FresnelTransmitter.h new file mode 100644 index 0000000..3884d02 --- /dev/null +++ b/src/BTDFs/FresnelTransmitter.h @@ -0,0 +1,59 @@ +// 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 __FRESNEL_TRANSMITTER__ +#define __FRESNEL_TRANSMITTER__ + +#include "BTDF.h" + +class FresnelTransmitter : public BTDF { +public: + + FresnelTransmitter() = default; + + ~FresnelTransmitter() = default; + + FresnelTransmitter(const FresnelTransmitter& pt); + + FresnelTransmitter(FresnelTransmitter&& pt) noexcept; + + FresnelTransmitter& operator=(const FresnelTransmitter& rhs); + + FresnelTransmitter& operator=(FresnelTransmitter&& rhs) noexcept; + + FresnelTransmitter* clone() const override; + + void set_eta_in(const float eta); + + void set_eta_out(const float eta); + + bool tir(const ShadeRec& sr) const; + + RGBColor f(const ShadeRec& sr, const Vector3D& wo, const Vector3D& wi) const override; + + RGBColor sample_f(const ShadeRec& sr, const Vector3D& wo, Vector3D& wt) const override; + + RGBColor rho(const ShadeRec& sr, const Vector3D& wo) const override; + +private: + + float eta_in = 1.0f; + float eta_out = 1.0f; + float kt = 0.0f; // TODO: what is kt? + float ior = 0.0f; // TODO: what is ior? +}; + +inline void FresnelTransmitter::set_eta_in(const float eta) { eta_in = eta; } + +inline void FresnelTransmitter::set_eta_out(const float eta) { eta_out = eta; } + +#endif diff --git a/src/BTDFs/PerfectTransmitter.cpp b/src/BTDFs/PerfectTransmitter.cpp index a0478cc..bc6ddb1 100644 --- a/src/BTDFs/PerfectTransmitter.cpp +++ b/src/BTDFs/PerfectTransmitter.cpp @@ -38,7 +38,7 @@ PerfectTransmitter& PerfectTransmitter::operator=(PerfectTransmitter&& pt) noexc return *this; } -PerfectTransmitter* PerfectTransmitter::clone() { return new PerfectTransmitter(*this); } +PerfectTransmitter* PerfectTransmitter::clone() const { return new PerfectTransmitter(*this); } // tests for total internal reflection diff --git a/src/BTDFs/PerfectTransmitter.h b/src/BTDFs/PerfectTransmitter.h index 4dc5a89..c262e2a 100644 --- a/src/BTDFs/PerfectTransmitter.h +++ b/src/BTDFs/PerfectTransmitter.h @@ -30,7 +30,7 @@ class PerfectTransmitter : public BTDF { PerfectTransmitter& operator=(PerfectTransmitter&& rhs) noexcept; - PerfectTransmitter* clone() override; + PerfectTransmitter* clone() const override; void set_kt(const float k); diff --git a/src/Materials/Dielectric.cpp b/src/Materials/Dielectric.cpp new file mode 100644 index 0000000..72b34b6 --- /dev/null +++ b/src/Materials/Dielectric.cpp @@ -0,0 +1,13 @@ +// 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 "Dielectric.h" \ No newline at end of file diff --git a/src/Materials/Dielectric.h b/src/Materials/Dielectric.h new file mode 100644 index 0000000..a1b7e14 --- /dev/null +++ b/src/Materials/Dielectric.h @@ -0,0 +1,22 @@ +// 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 __DIELECTRIC__ +#define __DIELECTRIC__ + +class Dielectric { + +// TODO: implement, 28.3 Implementation, page 601 + +}; + +#endif \ No newline at end of file