ssf_specular_dielectric_dielectric_interface.c (4470B)
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_bsdf_c.h" 18 #include "ssf_optics.h" 19 20 #include <rsys/double3.h> 21 #include <star/ssp.h> 22 23 struct specular_dielectric_dielectric_interface { 24 struct ssf_fresnel* fresnel; 25 double eta_i; /* Refractive index of the incoming medium */ 26 double eta_t; /* Refractive index of the transmissive medium */ 27 }; 28 29 /******************************************************************************* 30 * Private functions 31 ******************************************************************************/ 32 static res_T 33 ssf_specular_dielectric_dielectric_interface_init 34 (struct mem_allocator* allocator, void* data) 35 { 36 struct specular_dielectric_dielectric_interface* bsdf = data; 37 ASSERT(bsdf); 38 return ssf_fresnel_create 39 (allocator, &ssf_fresnel_dielectric_dielectric, &bsdf->fresnel); 40 } 41 42 static void 43 ssf_specular_dielectric_dielectric_interface_release(void* data) 44 { 45 struct specular_dielectric_dielectric_interface* bsdf = data; 46 SSF(fresnel_ref_put(bsdf->fresnel)); 47 } 48 49 static double 50 ssf_specular_dielectric_dielectric_interface_sample 51 (void* data, 52 struct ssp_rng* rng, 53 const double wo[3], 54 const double N[3], 55 double wi[3], 56 int* type, 57 double* pdf) 58 { 59 struct specular_dielectric_dielectric_interface* bsdf = data; 60 struct ssf_fresnel* fresnel; 61 double wt[3]; 62 double *refracted; 63 double cos_wo_N; 64 double eta; /* Ratio of eta_i / eta_t */ 65 double R; 66 ASSERT(bsdf && rng && wi && N && wo); 67 ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); 68 ASSERT(d3_dot(wo, N) > -1.e-6); 69 (void)rng; 70 71 eta = bsdf->eta_i / bsdf->eta_t; 72 refracted = refract(wt, wo, N, eta); 73 if(!refracted) { /* Total reflection */ 74 reflect(wi, wo, N); 75 if(pdf) *pdf = INF; 76 if(type) *type = SSF_SPECULAR | SSF_REFLECTION; 77 return 1; 78 } 79 fresnel = bsdf->fresnel; 80 81 cos_wo_N = MMAX(0.0, d3_dot(wo, N)); 82 SSF(fresnel_dielectric_dielectric_setup(fresnel, bsdf->eta_i, bsdf->eta_t)); 83 R = ssf_fresnel_eval(fresnel, cos_wo_N); 84 85 if(pdf) *pdf = INF; 86 87 /* Sample the output direction wrt R */ 88 if(ssp_rng_canonical(rng) < R) { 89 reflect(wi, wo, N); 90 if(type) *type = SSF_SPECULAR | SSF_REFLECTION; 91 } else { 92 d3_set(wi, refracted); 93 if(type) *type = SSF_SPECULAR | SSF_TRANSMISSION; 94 } 95 return 1; 96 } 97 98 static double 99 ssf_specular_dielectric_dielectric_interface_eval 100 (void* bsdf, const double wo[3], const double N[3], const double wi[3]) 101 { 102 (void)bsdf, (void)wo, (void)N, (void)wi; 103 return 0.0; 104 } 105 106 static double 107 ssf_specular_dielectric_dielectric_interface_pdf 108 (void* bsdf, const double wo[3], const double N[3], const double wi[3]) 109 { 110 (void)bsdf, (void)wo, (void)N, (void)wi; 111 return 0.0; 112 } 113 114 /******************************************************************************* 115 * Exported symbols 116 ******************************************************************************/ 117 const struct ssf_bsdf_type ssf_specular_dielectric_dielectric_interface = { 118 ssf_specular_dielectric_dielectric_interface_init, 119 ssf_specular_dielectric_dielectric_interface_release, 120 ssf_specular_dielectric_dielectric_interface_sample, 121 ssf_specular_dielectric_dielectric_interface_eval, 122 ssf_specular_dielectric_dielectric_interface_pdf, 123 sizeof(struct specular_dielectric_dielectric_interface), 124 ALIGNOF(struct specular_dielectric_dielectric_interface) 125 }; 126 127 res_T 128 ssf_specular_dielectric_dielectric_interface_setup 129 (struct ssf_bsdf* bsdf, 130 const double eta_i, 131 const double eta_t) 132 { 133 struct specular_dielectric_dielectric_interface* data; 134 135 if(!bsdf || eta_i <= 0 || eta_t <= 0) 136 return RES_BAD_ARG; 137 if(!BSDF_TYPE_EQ(&bsdf->type, &ssf_specular_dielectric_dielectric_interface)) 138 return RES_BAD_ARG; 139 140 data = bsdf->data; 141 142 data->eta_i = eta_i; 143 data->eta_t = eta_t; 144 return RES_OK; 145 } 146