test_ssf_specular_dielectric_dielectric_reflection.c (4189B)
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_optics.h" 18 #include "test_ssf_utils.h" 19 20 #include <rsys/double3.h> 21 22 int 23 main(int argc, char** argv) 24 { 25 const size_t NSTEPS = 10000; 26 struct mem_allocator allocator; 27 struct ssp_rng* rng; 28 struct ssf_bsdf* bsdf; 29 struct ssf_bsdf* dummy; 30 const double eta_i = 1.00027; 31 const double eta_t = 1.5; 32 const double eta = eta_i/eta_t; 33 double N[3]; 34 double wo[3]; 35 double wi[3]; 36 double tmp[3]; 37 double R; 38 double pdf; 39 double sum_t, sum_t2, t; 40 double sum_r, sum_r2, r; 41 size_t i; 42 int type; 43 (void)argc, (void)argv; 44 45 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 46 CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK); 47 CHK(ssf_bsdf_create(&allocator, 48 &ssf_specular_dielectric_dielectric_interface, &bsdf) == RES_OK); 49 CHK(ssf_bsdf_create(&allocator, &bsdf_dummy, &dummy) == RES_OK); 50 51 #define SETUP ssf_specular_dielectric_dielectric_interface_setup 52 CHK(SETUP(NULL, 0, 0) == RES_BAD_ARG); 53 CHK(SETUP(bsdf, 0, 0) == RES_BAD_ARG); 54 CHK(SETUP(NULL, 1, 0) == RES_BAD_ARG); 55 CHK(SETUP(bsdf, 1, 0) == RES_BAD_ARG); 56 CHK(SETUP(NULL, 0, 1) == RES_BAD_ARG); 57 CHK(SETUP(bsdf, 0, 1) == RES_BAD_ARG); 58 CHK(SETUP(NULL, 1, 1) == RES_BAD_ARG); 59 CHK(SETUP(bsdf, 1, 1) == RES_OK); 60 CHK(SETUP(dummy, 1, 1) == RES_BAD_ARG); 61 CHK(SETUP(bsdf, 1.00027, 1.5) == RES_OK); 62 #undef SETUP 63 64 d3(N, 0, 1, 0); 65 66 /* Test transmission */ 67 d3(wo, 0, 1, 0); 68 R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); 69 CHK(R != 0); 70 CHK(IS_INF(pdf)); 71 CHK(d3_eq_eps(wi, d3(tmp,0,-1,0), 1.e-6)); 72 CHK(type == (SSF_SPECULAR | SSF_TRANSMISSION)); 73 74 /* Test reflection */ 75 d3(wo, 1, 0, 0); 76 R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); 77 CHK(R != 0); 78 CHK(IS_INF(pdf)); 79 CHK(d3_eq_eps(wi, d3(tmp,-1,0,0), 1.e-6)); 80 CHK(type == (SSF_SPECULAR | SSF_REFLECTION)); 81 82 d3_normalize(wo, d3(wo, 1, 0.0000001, 0)); 83 R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); 84 CHK(R == 1); 85 CHK(IS_INF(pdf)); 86 CHK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6) == 1); 87 CHK(type == (SSF_SPECULAR | SSF_REFLECTION)); 88 89 pdf = 0, type = 0; 90 CHK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, NULL, &pdf) == R); 91 CHK(IS_INF(pdf)); 92 CHK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, NULL) == R); 93 CHK(type == (SSF_SPECULAR | SSF_REFLECTION)); 94 CHK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, NULL, NULL) == R); 95 96 /* Check energy conservation */ 97 sum_t = sum_t2 = 0; 98 sum_r = sum_r2 = 0; 99 FOR_EACH(i, 0, NSTEPS) { 100 ssp_ran_hemisphere_cos(rng, wo, N, NULL); 101 R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, NULL); 102 if(type & SSF_TRANSMISSION) { 103 sum_t += R; 104 sum_t2 += R*R; 105 } else { 106 sum_r += R; 107 sum_r2 += R*R; 108 } 109 } 110 111 t = sum_t / (double)NSTEPS; 112 r = sum_r / (double)NSTEPS; 113 CHK(t > 0); 114 CHK(r > 0); 115 CHK(eq_eps(t + r, 1, 1.e-6)); 116 117 FOR_EACH(i, 0, NSTEPS) { 118 d3_normalize(wo, d3(wo,1,1,0)); 119 R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); 120 CHK(R != 0); 121 CHK(type & SSF_SPECULAR); 122 CHK(IS_INF(pdf)); 123 if(d3_eq_eps(wi, refract(tmp, wo, N, eta), 1.e-6)) { 124 CHK(type & SSF_TRANSMISSION); 125 } else { 126 CHK(d3_eq_eps(wi, reflect(tmp, wo, N), 1.e-6)); 127 CHK(type & SSF_REFLECTION); 128 } 129 CHK(ssf_bsdf_pdf(bsdf, wo, N, wi) == 0); 130 CHK(ssf_bsdf_eval(bsdf, wo, N, wi) == 0); 131 } 132 133 CHK(ssp_rng_ref_put(rng) == RES_OK); 134 CHK(ssf_bsdf_ref_put(bsdf) == RES_OK); 135 CHK(ssf_bsdf_ref_put(dummy) == RES_OK); 136 137 return 0; 138 }