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 0ca3fa94134299c2a3ab5dae27c3ac1c1f8210ef
parent e2517cae8e52cefc810118f775d4d2e03ad30f85
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  9 Sep 2016 10:13:44 +0200

Implement the fresnel term for dielectric surfaces

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssf_fresnel_c.h | 7+++++++
Asrc/ssf_fresnel_dielectric.c | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 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.c ssf_fresnel_no_op.c ssf_specular_reflection.c) rcmake_prepend_path(SSF_FILES_SRC ${SSF_SOURCE_DIR}) diff --git a/src/ssf_fresnel_c.h b/src/ssf_fresnel_c.h @@ -30,5 +30,12 @@ struct ssf_fresnel { struct mem_allocator* allocator; }; +#define FRESNEL_TYPE_EQ(A, B) \ + ( (A)->init == (B)->init \ + && (A)->release == (B)->release \ + && (A)->eval == (B)->eval \ + && (A)->sizeof_fresnel == (B)->sizeof_fresnel \ + && (A)->alignof_fresnel == (B)->alignof_fresnel) + #endif /* SSF_FRESNEL_C_H */ diff --git a/src/ssf_fresnel_dielectric.c b/src/ssf_fresnel_dielectric.c @@ -0,0 +1,106 @@ +/* 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 <rsys/math.h> +#include <math.h> + +struct fresnel_dielectric { + double lambda_i; + double lambda_t; +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static res_T +fresnel_dielectric_init(struct mem_allocator* allocator, void* fresnel) +{ + struct fresnel_dielectric* fd = fresnel; + (void)allocator; + ASSERT(fresnel); + fd->lambda_i = 0.0; + fd->lambda_t = 0.0; + return RES_OK; +} + +static void +fresnel_dielectric_release(void* fresnel) +{ + (void)fresnel; +} + +static double +fresnel_dielectric_eval(void* fresnel, const double cos_theta_i) +{ + const struct fresnel_dielectric* fd = fresnel; + double sin_theta_i; + double sin_theta_t; + double cos_theta_t; + double R_par; + double R_per; + ASSERT(fresnel && cos_theta_i >= 0); + + /* Use Snell's low to retrieve cos_theta_t: + * lambda_i * sin_theta_i = lambda_t * sin_theta_t */ + sin_theta_i = sqrt(MMAX(0.0, 1.0 - cos_theta_i*cos_theta_i)); + sin_theta_t = fd->lambda_i * sin_theta_i / fd->lambda_t; + if(sin_theta_t >= 1) return 1.0; /* Full reflection */ + cos_theta_t = sqrt(1.0 - sin_theta_t*sin_theta_t); + + /* Compute the reflectance for the light polarized with its electric field + * parallel to the plane of incidence */ + R_par = (fd->lambda_i*cos_theta_t - fd->lambda_t*cos_theta_i) + / (fd->lambda_i*cos_theta_t + fd->lambda_t*cos_theta_i); + R_par = fabs(R_par); + R_par = R_par * R_par; + + /* Compute the reflectance for the light polarized with its electric field + * perpendicular to the plane of incidence */ + R_per = (fd->lambda_i*cos_theta_i - fd->lambda_t*cos_theta_t) + / (fd->lambda_i*cos_theta_i + fd->lambda_t*cos_theta_t); + R_per = fabs(R_per); + R_per = R_per * R_per; + + return 0.5 * (R_par + R_per); +} + +/******************************************************************************* + * Exported symbols + ******************************************************************************/ +const struct ssf_fresnel_type ssf_fresnel_dielectric = { + fresnel_dielectric_init, + fresnel_dielectric_release, + fresnel_dielectric_eval, + sizeof(struct fresnel_dielectric), + ALIGNOF(struct fresnel_dielectric) +}; + +res_T +ssf_fresnel_dielectric_setup + (struct ssf_fresnel* fresnel, const double lambda_i, const double lambda_t) +{ + struct fresnel_dielectric* fd; + + if(!fresnel) return RES_BAD_ARG; + if(!FRESNEL_TYPE_EQ(&fresnel->type, &ssf_fresnel_dielectric)) + return RES_BAD_ARG; + fd = fresnel->data; + fd->lambda_i = lambda_i; + fd->lambda_t = lambda_t; + return RES_OK; +} +