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_conductor.c (3057B)


      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 
     19 #include <math.h>
     20 
     21 struct fresnel_dielectric_conductor {
     22   double eta_i; /* Refraction id of the dielectric medium */
     23   double eta_t; /* Real part of the refraction index */
     24   double eta_k_t; /* Imaginary part of the refraction index */
     25 };
     26 
     27 /*******************************************************************************
     28  * Private functions
     29  ******************************************************************************/
     30 /* Code from
     31  * https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ */
     32 static double
     33 fresnel_dielectric_conductor_eval(void* fresnel, const double cos_theta_i)
     34 {
     35   const struct fresnel_dielectric_conductor* fc = fresnel;
     36   double cos_theta_i2;
     37   double sin_theta_i2;
     38   double eta, eta_k, eta2, eta_k2;
     39   double t0, t1, t2, t3, t4;
     40   double a;
     41   double a2_add_b2;
     42   double Rp, Rs;
     43   ASSERT(fresnel && cos_theta_i >= 0 && fc->eta_i > 0);
     44 
     45   cos_theta_i2 = cos_theta_i * cos_theta_i;
     46   sin_theta_i2 = 1.0 - cos_theta_i2;
     47   eta = fc->eta_t / fc->eta_i; /* Real part */
     48   eta_k = fc->eta_k_t / fc->eta_i; /* Imaginary part */
     49   eta2 = eta*eta;
     50   eta_k2 = eta_k*eta_k;
     51 
     52   t0 = eta2 - eta_k2 - sin_theta_i2;
     53   a2_add_b2 = sqrt(t0*t0 + 4*eta2*eta_k2);
     54   t1 = a2_add_b2 + cos_theta_i2;
     55   a = sqrt(0.5 * (a2_add_b2 + t0));
     56   t2 = 2.0*a*cos_theta_i;
     57   Rs = (t1 - t2) / (t1 + t2);
     58 
     59   t3 = cos_theta_i2 * a2_add_b2 + sin_theta_i2 * sin_theta_i2;
     60   t4 = t2 * sin_theta_i2;
     61   Rp = Rs * (t3 - t4) / (t3 + t4);
     62   return 0.5 * (Rp + Rs);
     63 }
     64 
     65 /*******************************************************************************
     66  * Exported symbols
     67  ******************************************************************************/
     68 const struct ssf_fresnel_type ssf_fresnel_dielectric_conductor = {
     69   NULL,
     70   NULL,
     71   fresnel_dielectric_conductor_eval,
     72   sizeof(struct fresnel_dielectric_conductor),
     73   ALIGNOF(struct fresnel_dielectric_conductor)
     74 };
     75 
     76 res_T
     77 ssf_fresnel_dielectric_conductor_setup
     78   (struct ssf_fresnel* fresnel,
     79    const double eta_i,
     80    const double eta_t,
     81    const double eta_k_t)
     82 {
     83   struct fresnel_dielectric_conductor* fc;
     84   if(!fresnel
     85   || !FRESNEL_TYPE_EQ(&fresnel->type, &ssf_fresnel_dielectric_conductor)) {
     86     return RES_BAD_ARG;
     87   }
     88   fc = fresnel->data;
     89   fc->eta_i = eta_i;
     90   fc->eta_t = eta_t;
     91   fc->eta_k_t = eta_k_t;
     92   return RES_OK;
     93 }
     94