star-sf

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

ssf_fresnel_dielectric_dielectric.c (3045B)


      1 /* Copyright (C) 2016-2018, 2021-2025 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "ssf.h"
     17 #include "ssf_fresnel_c.h"
     18 #include <rsys/math.h>
     19 #include <math.h>
     20 
     21 struct fresnel_dielectric_dielectric {
     22   double eta_i;
     23   double eta_t;
     24 };
     25 
     26 /*******************************************************************************
     27  * Private functions
     28  ******************************************************************************/
     29 static double
     30 fresnel_dielectric_dielectric_eval(void* fresnel, const double cos_theta_i)
     31 {
     32   const struct fresnel_dielectric_dielectric* fd = fresnel;
     33   double sin_theta_i;
     34   double sin_theta_t;
     35   double cos_theta_t;
     36   double Rp; /* Parallel */
     37   double Rs; /* Orthogonal */
     38   ASSERT(fresnel && cos_theta_i >= 0 && fd->eta_t > 0 && fd->eta_i > 0);
     39 
     40   /* Use Snell's low to retrieve cos_theta_t:
     41    * eta_i * sin_theta_i = eta_t * sin_theta_t */
     42   sin_theta_i = sqrt(MMAX(0.0, 1.0 - cos_theta_i*cos_theta_i));
     43   sin_theta_t = fd->eta_i * sin_theta_i / fd->eta_t;
     44   if(sin_theta_t >= 1) return 1.0; /* Full reflection */
     45   cos_theta_t = sqrt(1.0 - sin_theta_t*sin_theta_t);
     46 
     47   /* Compute the reflectance for the light polarized with its electric field
     48    * parallel to the plane of incidence */
     49   Rp = (fd->eta_i*cos_theta_t - fd->eta_t*cos_theta_i)
     50      / (fd->eta_i*cos_theta_t + fd->eta_t*cos_theta_i);
     51   Rp = Rp * Rp;
     52 
     53   /* Compute the reflectance for the light polarized with its electric field
     54    * perpendicular to the plane of incidence */
     55   Rs = (fd->eta_i*cos_theta_i - fd->eta_t*cos_theta_t)
     56      / (fd->eta_i*cos_theta_i + fd->eta_t*cos_theta_t);
     57   Rs = Rs * Rs;
     58 
     59   return 0.5 * (Rp + Rs);
     60 }
     61 
     62 /*******************************************************************************
     63  * Exported symbols
     64  ******************************************************************************/
     65 const struct ssf_fresnel_type ssf_fresnel_dielectric_dielectric = {
     66   NULL,
     67   NULL,
     68   fresnel_dielectric_dielectric_eval,
     69   sizeof(struct fresnel_dielectric_dielectric),
     70   ALIGNOF(struct fresnel_dielectric_dielectric)
     71 };
     72 
     73 res_T
     74 ssf_fresnel_dielectric_dielectric_setup
     75   (struct ssf_fresnel* fresnel, const double eta_i, const double eta_t)
     76 {
     77   struct fresnel_dielectric_dielectric* fd;
     78   if(!fresnel
     79   || !FRESNEL_TYPE_EQ(&fresnel->type, &ssf_fresnel_dielectric_dielectric)) {
     80     return RES_BAD_ARG;
     81   }
     82   fd = fresnel->data;
     83   fd->eta_i = eta_i;
     84   fd->eta_t = eta_t;
     85   return RES_OK;
     86 }
     87