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_lambertian_reflection.c (4591B)


      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 #include <rsys/double3.h>
     20 #include <rsys/double33.h>
     21 
     22 int
     23 main(int argc, char** argv)
     24 {
     25   const size_t NSTEPS = 100000;
     26   struct mem_allocator allocator;
     27   struct ssp_rng* rng;
     28   struct ssf_bsdf* brdf;
     29   struct ssf_bsdf* dummy;
     30   double E, SE, V;
     31   double sum;
     32   double sum_sqr;
     33   double basis[9];
     34   double wo[3], wi[3];
     35   double N[3];
     36   double pdf;
     37   double R;
     38   size_t i;
     39   int type;
     40   (void)argc, (void)argv;
     41 
     42   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
     43   CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng) == RES_OK);
     44 
     45   CHK(ssf_bsdf_create(&allocator, &ssf_lambertian_reflection, &brdf) == RES_OK);
     46   CHK(ssf_bsdf_create(&allocator, &bsdf_dummy, &dummy) == RES_OK);
     47 
     48   CHK(ssf_lambertian_reflection_setup(NULL, -1.0) == RES_BAD_ARG);
     49   CHK(ssf_lambertian_reflection_setup(brdf, -1.0) == RES_BAD_ARG);
     50   CHK(ssf_lambertian_reflection_setup(NULL, 1.0) == RES_BAD_ARG);
     51   CHK(ssf_lambertian_reflection_setup(brdf, 1.0) == RES_OK);
     52   CHK(ssf_lambertian_reflection_setup(brdf, 0.0) == RES_OK);
     53   CHK(ssf_lambertian_reflection_setup(brdf, 1.1) == RES_BAD_ARG);
     54   CHK(ssf_lambertian_reflection_setup(dummy, 0.0) == RES_BAD_ARG);
     55 
     56   d3(N, 0.0, 0.0, 1.0);
     57   d3_normalize(wo, d3(wo, 1.0, 0.0, 1.0));
     58   R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
     59   CHK(eq_eps(wi[2]/PI, pdf, 1.e-6) == 1);
     60   CHK(R == 0);
     61   CHK(type == (SSF_DIFFUSE|SSF_REFLECTION));
     62 
     63   CHK(ssf_lambertian_reflection_setup(brdf, 0.7) == RES_OK);
     64   R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
     65   CHK(eq_eps(R, 0.7, 1.e-6) == 1);
     66   CHK(eq_eps(pdf, d3_dot(wi, N)/PI, 1.e-6) == 1);
     67   CHK(type == (SSF_DIFFUSE|SSF_REFLECTION));
     68 
     69   pdf = 0, type = 0;
     70   CHK(ssf_bsdf_sample(brdf, rng, wo, N, wi, NULL, &pdf) == R);
     71   CHK(eq_eps(pdf, d3_dot(wi, N)/PI, 1.e-6) == 1);
     72   CHK(ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, NULL) == R);
     73   CHK(type == (SSF_DIFFUSE|SSF_REFLECTION));
     74   CHK(ssf_bsdf_sample(brdf, rng, wo, N, wi, NULL, NULL) == R);
     75 
     76   d3_normalize(wo, d3(wo, 1.0, 0.0, 1.0));
     77   N[0] = ssp_rng_uniform_double(rng, -1, 1);
     78   N[1] = ssp_rng_uniform_double(rng, -1, 1);
     79   N[2] = ssp_rng_uniform_double(rng, -1, 1);
     80   d3_normalize(N, N);
     81   d33_basis(basis, N);
     82   d33_muld3(wo, basis, wo);
     83 
     84   sum = sum_sqr = 0;
     85   FOR_EACH(i, 0, NSTEPS) {
     86     double cos_wi_N;
     87     R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf) / PI;
     88     cos_wi_N = d3_dot(wi, N);
     89     CHK(eq_eps(R, 0.7/PI, 1.e-6) == 1);
     90     CHK(eq_eps(cos_wi_N/PI, pdf, 1.e-6) == 1);
     91     CHK(type == (SSF_DIFFUSE|SSF_REFLECTION));
     92     sum += cos_wi_N;
     93     sum_sqr += cos_wi_N * cos_wi_N;
     94   }
     95   E = sum/(double)NSTEPS;
     96   V = sum_sqr/(double)NSTEPS - E*E;
     97   SE = sqrt(V/(double)NSTEPS);
     98   CHK(eq_eps(E, 2.0/3.0, SE) == 1);
     99 
    100   sum = sum_sqr = 0;
    101   FOR_EACH(i, 0, NSTEPS) {
    102     double cos_wi_N;
    103     double w;
    104 
    105     R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf)/PI;
    106     cos_wi_N = d3_dot(wi, N);
    107     CHK(eq_eps(R, 0.7/PI, 1.e-6) == 1);
    108     CHK(eq_eps(cos_wi_N/PI, pdf, 1.e-6) == 1);
    109     CHK(type == (SSF_DIFFUSE|SSF_REFLECTION));
    110     w = cos_wi_N*cos_wi_N;
    111     sum += w;
    112     sum_sqr += w*w;
    113   }
    114 
    115   E = sum/(double)NSTEPS;
    116   V = sum_sqr/(double)NSTEPS - E*E;
    117   SE = sqrt(V/(double)NSTEPS);
    118   CHK(eq_eps(E, 2.0/4.0, 2.0*SE) == 1);
    119   CHK(eq_eps(SE, 1.0/sqrt((double)NSTEPS) * sqrt(1.0/3.0 - 1.0/4.0), 1.e-6) == 1);
    120 
    121   FOR_EACH(i, 0, NSTEPS) {
    122     double val;
    123     R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
    124     CHK(eq_eps(R, 0.7, 1.e-6) == 1);
    125     val = ssf_bsdf_eval(brdf, wo, N, wi) * d3_dot(wi, N);
    126     CHK(eq_eps(val, R * pdf, 1.e-6) == 1);
    127     CHK(type == (SSF_DIFFUSE|SSF_REFLECTION));
    128   }
    129 
    130   CHK(ssf_bsdf_ref_put(brdf) == RES_OK);
    131   CHK(ssf_bsdf_ref_put(dummy) == RES_OK);
    132   CHK(ssp_rng_ref_put(rng) == RES_OK);
    133 
    134   check_memory_allocator(&allocator);
    135   mem_shutdown_proxy_allocator(&allocator);
    136   CHK(mem_allocated_size() == 0);
    137   return 0;
    138 }
    139