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 408e9bc133b2de5581f1bc37a28414e84f69c8ed
parent c434ba7c1e31b931360e64772f952dde6a283652
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Sat, 10 Sep 2016 14:34:31 +0200

Implement the Fresnel term of the dielectric/conductor interfaces

Diffstat:
Mcmake/CMakeLists.txt | 1+
Asrc/ssf_fresnel_dielectric_conductor.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -52,6 +52,7 @@ set(SSF_FILES_SRC ssf_bsdf.c ssf_bxdf.c ssf_fresnel.c + ssf_fresnel_dielectric_conductor.c ssf_fresnel_dielectric_dielectric.c ssf_fresnel_no_op.c ssf_specular_reflection.c) diff --git a/src/ssf_fresnel_dielectric_conductor.c b/src/ssf_fresnel_dielectric_conductor.c @@ -0,0 +1,113 @@ +/* Copyright (C) |Meso|Star> 2016 (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_fresnel_c.h" + +#include <math.h> + +struct fresnel_dielectric_conductor { + double eta_i; /* Refraction id of the dielectric medium */ + double eta_t; /* Real part of the refraction index */ + double eta_k_t; /* Imaginary part of the refraction index */ +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static res_T +fresnel_dielectric_conductor_init + (struct mem_allocator* allocator, void* fresnel) +{ + struct fresnel_dielectric_conductor* fc = fresnel; + (void)allocator; + ASSERT(fresnel); + fc->eta_i = 0.0; + fc->eta_t = 0.0; + fc->eta_k_t = 0.0; + return RES_OK; +} + +static void +fresnel_dielectric_conductor_release(void* fresnel) +{ + (void)fresnel; +} + +/* Code from + * https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ */ +static double +fresnel_dielectric_conductor_eval(void* fresnel, const double cos_theta_i) +{ + const struct fresnel_dielectric_conductor* fc = fresnel; + double cos_theta_i2; + double sin_theta_i2; + double eta, eta_k, eta2, eta_k2; + double t0, t1, t2, t3, t4; + double a; + double a2_add_b2; + double Rp, Rs; + ASSERT(fresnel && cos_theta_i >= 0); + + cos_theta_i2 = cos_theta_i * cos_theta_i; + sin_theta_i2 = 1.0 - cos_theta_i2; + eta = fc->eta_t / fc->eta_i; /* Real part */ + eta_k = fc->eta_k_t / fc->eta_i; /* Imaginary part */ + eta2 = eta*eta; + eta_k2 = eta_k*eta_k; + + t0 = eta2 - eta_k2 - sin_theta_i2; + a2_add_b2 = sqrt(t0*t0 + 4*eta2*eta_k2); + t1 = a2_add_b2 + cos_theta_i2; + a = sqrt(0.5 * (a2_add_b2 + t0)); + t2 = 2.0*a*cos_theta_i; + Rs = (t1 - t2) / (t1 + t2); + + t3 = cos_theta_i2 * a2_add_b2 + sin_theta_i2 * sin_theta_i2; + t4 = t2 * sin_theta_i2; + Rp = Rs * (t3 - t4) / (t3 + t4); + return 0.5 * (Rp + Rs); +} + +/******************************************************************************* + * Exported symbols + ******************************************************************************/ +const struct ssf_fresnel_type ssf_fresnel_dielectric_conductor = { + fresnel_dielectric_conductor_init, + fresnel_dielectric_conductor_release, + fresnel_dielectric_conductor_eval, + sizeof(struct fresnel_dielectric_conductor), + ALIGNOF(struct fresnel_dielectric_conductor) +}; + +res_T +ssf_fresnel_dielectric_conductor_setup + (struct ssf_fresnel* fresnel, + const double eta_i, + const double eta_t, + const double eta_k_t) +{ + struct fresnel_dielectric_conductor* fc; + if(!fresnel + || !FRESNEL_TYPE_EQ(&fresnel->type, &ssf_fresnel_dielectric_conductor)) { + return RES_BAD_ARG; + } + fc = fresnel->data; + fc->eta_i = eta_i; + fc->eta_t = eta_t; + fc->eta_k_t = eta_k_t; + return RES_OK; +} +