test_ssf_phase_rayleigh.c (2497B)
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 "test_ssf_utils.h" 18 19 #define NSAMPS 10000 20 21 int 22 main(int argc, char** argv) 23 { 24 struct mem_allocator allocator; 25 struct ssf_phase* phase; 26 struct ssp_rng* rng; 27 double wo[3]; 28 double wi[3]; 29 double sum_cos = 0; 30 double sum_cos_sqr = 0; 31 double sum_cos_sqr2 = 0; 32 double E, V, SE; 33 size_t i; 34 (void)argc, (void)argv; 35 36 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 37 CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK); 38 39 CHK(ssf_phase_create(&allocator, &ssf_phase_rayleigh, &phase) == RES_OK); 40 41 ssp_ran_sphere_uniform(rng, wo, NULL); 42 FOR_EACH(i, 0, NSAMPS) { 43 double w[3]; 44 double weight; 45 double pdf; 46 double ref; 47 double r; 48 ssf_phase_sample(phase, rng, wo, wi, &pdf); 49 CHK(d3_is_normalized(wi)); 50 CHK(eq_eps(ssf_phase_pdf(phase, wo, wi), pdf, 1.e-6f)); 51 d3_minus(w, wo); 52 weight = d3_dot(wo, wi); 53 sum_cos += weight; 54 sum_cos_sqr += weight*weight; 55 sum_cos_sqr2 += weight*weight*weight*weight; 56 57 r = ssf_phase_eval(phase, wo, wi); 58 ref = 3.0/(16.0*PI)*(1.0+weight*weight); 59 CHK(eq_eps(r, ref, 1.e-6)); 60 CHK(eq_eps(r, pdf, 1.e-6)); 61 } 62 63 /* On average cos(-wo,wi) should be 0 */ 64 E = sum_cos / NSAMPS; 65 V = sum_cos_sqr / NSAMPS - E*E; 66 SE = sqrt(V/NSAMPS); 67 CHK(eq_eps(E, 0, SE*3)); 68 69 /* On average cos(-wo,wi)^2 should be 2/5 */ 70 E = sum_cos_sqr / NSAMPS; 71 V = sum_cos_sqr2 / NSAMPS - E*E; 72 SE = sqrt(V/NSAMPS); 73 CHK(eq_eps(E, 2.0/5.0, SE*3)); 74 75 ssf_phase_sample(phase, rng, wo, wi, NULL); 76 CHK(d3_is_normalized(wi)); 77 78 CHK(ssf_phase_ref_put(phase) == RES_OK); 79 CHK(ssp_rng_ref_put(rng) == RES_OK); 80 81 check_memory_allocator(&allocator); 82 mem_shutdown_proxy_allocator(&allocator); 83 CHK(mem_allocated_size() == 0); 84 return 0; 85 }