star-sf

Set of surface and volume scattering functions
git clone git://git.meso-star.fr/star-sf.git
Log | Files | Refs | README | LICENSE

commit e7d8ae9ccff234538fd7b8f8de1637bb95798a69
parent 0a569165b52292bd52dac89680da988386940ada
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 25 Aug 2017 16:29:01 +0200

First try at a dielectric/dielectric specular interface.

That includes both reflection and transmission.

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssf.h | 9+++++++++
Asrc/ssf_specular_dielectric_dielectric_interface.c | 146+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 156 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -63,6 +63,7 @@ set(SSF_FILES_SRC ssf_lambertian_reflection.c ssf_microfacet_distribution.c ssf_microfacet_reflection.c + ssf_specular_dielectric_dielectric_interface.c ssf_specular_reflection.c ssf_specular_transmission.c ssf_thin_specular_dielectric.c) diff --git a/src/ssf.h b/src/ssf.h @@ -208,6 +208,9 @@ SSF_API const struct ssf_bxdf_type ssf_microfacet2_reflection; * by the user. */ SSF_API const struct ssf_bxdf_type ssf_thin_specular_dielectric; + +SSF_API const struct ssf_bxdf_type ssf_specular_dielectric_dielectric_interface; + /* Dirac distribution whose incoming direction `wi' is refracted wrt N and a * dielectric/dielectric fresnel term `Fr'. * fr(wo, wi) = (1 - Fr(|wi.N|)) * delta(wo - Refract(wi, N)) / |wi.N| @@ -397,6 +400,12 @@ ssf_thin_specular_dielectric_setup const double thickness); /* Thickness of the slab */ SSF_API res_T +ssf_specular_dielectric_dielectric_interface_setup + (struct ssf_bxdf* bxdf, + const double eta_i, + const double eta_t); + +SSF_API res_T ssf_specular_transmission_setup (struct ssf_bxdf* data, const double eta_i, /* Refraction id of the medium the ray travels in */ diff --git a/src/ssf_specular_dielectric_dielectric_interface.c b/src/ssf_specular_dielectric_dielectric_interface.c @@ -0,0 +1,146 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "ssf.h" +#include "ssf_bxdf_c.h" +#include "ssf_optics.h" + +#include <rsys/double3.h> +#include <star/ssp.h> + +struct specular_dielectric_dielectric_interface { + struct ssf_fresnel* fresnel; + double eta_i; /* Refractive index of the incoming medium */ + double eta_t; /* Refractive index of the transmissive medium */ +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static res_T +ssf_specular_dielectric_dielectric_interface_init + (struct mem_allocator* allocator, void* bxdf) +{ + struct specular_dielectric_dielectric_interface* bsdf = bxdf; + ASSERT(bxdf); + return ssf_fresnel_create + (allocator, &ssf_fresnel_dielectric_dielectric, &bsdf->fresnel); +} + +static void +ssf_specular_dielectric_dielectric_interface_release(void* bxdf) +{ + struct specular_dielectric_dielectric_interface* bsdf = bxdf; + SSF(fresnel_ref_put(bsdf->fresnel)); +} + +static double +ssf_specular_dielectric_dielectric_interface_sample + (void* bxdf, + struct ssp_rng* rng, + const double wo[3], + const double N[3], + double wi[3], + int* type, + double* pdf) +{ + struct specular_dielectric_dielectric_interface* bsdf = bxdf; + struct ssf_fresnel* fresnel; + double wt[3]; + double *refracted; + double cos_wo_N; + double eta; /* Ratio of eta_i / eta_t */ + double R; + ASSERT(bxdf && rng && wi && N && wo && type && pdf); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); + ASSERT(d3_dot(wo, N) > -1.e-6); + (void)rng; + + eta = bsdf->eta_i / bsdf->eta_t; + refracted = refract(wt, wo, N, eta); + if(!refracted) { /* Total reflection */ + reflect(wi, wo, N); + *pdf = INF; + *type = SSF_SPECULAR | SSF_REFLECTION; + return 1; + } + fresnel = bsdf->fresnel; + + cos_wo_N = MMAX(0.0, d3_dot(wo, N)); + SSF(fresnel_dielectric_dielectric_setup(fresnel, bsdf->eta_i, bsdf->eta_t)); + R = ssf_fresnel_eval(fresnel, cos_wo_N); + + *pdf = INF; + + /* Sample the output direction wrt R */ + if(ssp_rng_canonical(rng) < R) { + reflect(wi, wo, N); + *type = SSF_SPECULAR | SSF_REFLECTION; + } else { + d3_set(wi, refracted); + *type = SSF_SPECULAR | SSF_TRANSMISSION; + } + return 1; +} + +static double +ssf_specular_dielectric_dielectric_interface_eval + (void* bxdf, const double wo[3], const double N[3], const double wi[3]) +{ + (void)bxdf, (void)wo, (void)N, (void)wi; + return 0.0; +} + +static double +ssf_specular_dielectric_dielectric_interface_pdf + (void* bxdf, const double wo[3], const double N[3], const double wi[3]) +{ + (void)bxdf, (void)wo, (void)N, (void)wi; + return 0.0; +} + +/******************************************************************************* + * Exported symbols + ******************************************************************************/ +const struct ssf_bxdf_type ssf_specular_dielectric_dielectric_interface = { + ssf_specular_dielectric_dielectric_interface_init, + ssf_specular_dielectric_dielectric_interface_release, + ssf_specular_dielectric_dielectric_interface_sample, + ssf_specular_dielectric_dielectric_interface_eval, + ssf_specular_dielectric_dielectric_interface_pdf, + sizeof(struct specular_dielectric_dielectric_interface), + ALIGNOF(struct specular_dielectric_dielectric_interface) +}; + +res_T +ssf_specular_dielectric_dielectric_interface_setup + (struct ssf_bxdf* bxdf, + const double eta_i, + const double eta_t) +{ + struct specular_dielectric_dielectric_interface* bsdf; + + if(!bxdf || eta_i <= 0 || eta_t <= 0) + return RES_BAD_ARG; + if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_specular_dielectric_dielectric_interface)) + return RES_BAD_ARG; + + bsdf = bxdf->data; + + bsdf->eta_i = eta_i; + bsdf->eta_t = eta_t; + return RES_OK; +} +