star-sf

Set of surface and volume scattering functions
git clone git://git.meso-star.fr/star-sf.git
Log | Files | Refs | README | LICENSE

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 }