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