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_utils.h (6927B)


      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 #ifndef TEST_SSF_UTILS_H
     17 #define TEST_SSF_UTILS_H
     18 
     19 #include <rsys/double33.h>
     20 #include <rsys/math.h>
     21 #include <rsys/mem_allocator.h>
     22 
     23 #include <star/ssp.h>
     24 
     25 #include <stdio.h>
     26 
     27 #ifdef COMPILER_CL
     28   #pragma warning(disable:4324) /* Structre was padded due to alignment */
     29 #endif
     30 
     31 /*******************************************************************************
     32  * Dummy BSDF type
     33  ******************************************************************************/
     34 static res_T
     35 bsdf_dummy_init(struct mem_allocator* allocator, void* bsdf)
     36 {
     37   (void)allocator, (void)bsdf;
     38   return RES_OK;
     39 }
     40 
     41 static void
     42 bsdf_dummy_release(void* bsdf)
     43 {
     44   (void)bsdf;
     45 }
     46 
     47 static double
     48 bsdf_dummy_sample
     49   (void* bsdf,
     50    struct ssp_rng* rng,
     51    const double w[3],
     52    const double N[3],
     53    double dir[3],
     54    int* type,
     55    double* pdf)
     56 {
     57   (void)bsdf, (void)rng, (void)w, (void)N, (void)dir, (void)type, (void)pdf;
     58   return 0.0;
     59 }
     60 
     61 static double
     62 bsdf_dummy_eval
     63   (void* bsdf,
     64    const double wo[3],
     65    const double N[3],
     66    const double wi[3])
     67 {
     68   (void)bsdf, (void)wo, (void)N, (void)wi;
     69   return 0.0;
     70 }
     71 
     72 static double
     73 bsdf_dummy_pdf
     74   (void* bsdf,
     75    const double wo[3],
     76    const double N[3],
     77    const double wi[3])
     78 {
     79   (void)bsdf, (void)wo, (void)N, (void)wi;
     80   return 0.0;
     81 }
     82 
     83 static const struct ssf_bsdf_type bsdf_dummy = {
     84   bsdf_dummy_init,
     85   bsdf_dummy_release,
     86   bsdf_dummy_sample,
     87   bsdf_dummy_eval,
     88   bsdf_dummy_pdf,
     89   0, 1
     90 };
     91 
     92 /*******************************************************************************
     93  * Dummy Fresnel type
     94  ******************************************************************************/
     95 static res_T
     96 fresnel_dummy_init(struct mem_allocator* allocator, void* fresnel)
     97 {
     98   (void)allocator, (void)fresnel;
     99   return RES_OK;
    100 }
    101 
    102 static void
    103 fresnel_dummy_release(void* fresnel)
    104 {
    105   (void)fresnel;
    106 }
    107 
    108 static double
    109 fresnel_dummy_eval
    110   (void* fresnel,
    111    const double cos_theta_i)
    112 {
    113   (void)fresnel, (void)cos_theta_i;
    114   return 0.0;
    115 }
    116 
    117 static const struct ssf_fresnel_type fresnel_dummy = {
    118   fresnel_dummy_init,
    119   fresnel_dummy_release,
    120   fresnel_dummy_eval,
    121   0, 1
    122 };
    123 
    124 /*******************************************************************************
    125  * Dummy microfacet distribution type
    126  ******************************************************************************/
    127 static res_T
    128 microfacet_dummy_init(struct mem_allocator* allocator, void* distrib)
    129 {
    130   (void)allocator, (void)distrib;
    131   return RES_OK;
    132 }
    133 
    134 static void
    135 microfacet_dummy_release(void* distrib)
    136 {
    137   (void)distrib;
    138 }
    139 
    140 static void
    141 microfacet_dummy_sample
    142   (void* distrib,
    143    struct ssp_rng* rng,
    144    const double N[3],
    145    double dir[3],
    146    double* pdf)
    147 {
    148   (void)distrib, (void)rng, (void)N, (void)dir, (void)pdf;
    149 }
    150 
    151 static double
    152 microfacet_dummy_eval
    153   (void* distrib,
    154    const double N[3],
    155    const double wi[3])
    156 {
    157   (void)distrib, (void)N, (void)wi;
    158   return 0.0;
    159 }
    160 
    161 static double
    162 microfacet_dummy_pdf
    163   (void* distrib,
    164    const double N[3],
    165    const double wi[3])
    166 {
    167   (void)distrib, (void)N, (void)wi;
    168   return 0.0;
    169 }
    170 
    171 static const struct ssf_microfacet_distribution_type microfacet_dummy = {
    172   microfacet_dummy_init,
    173   microfacet_dummy_release,
    174   microfacet_dummy_sample,
    175   microfacet_dummy_eval,
    176   microfacet_dummy_pdf,
    177   0, 1
    178 };
    179 
    180 /*******************************************************************************
    181  * Dummy Phase function type
    182  ******************************************************************************/
    183 static res_T
    184 phase_dummy_init(struct mem_allocator* allocator, void* phase)
    185 {
    186   (void)allocator, (void)phase;
    187   return RES_OK;
    188 }
    189 
    190 static void
    191 phase_dummy_release(void* phase)
    192 {
    193   (void)phase;
    194 }
    195 
    196 static void
    197 phase_dummy_sample
    198   (void* phase,
    199    struct ssp_rng* rng,
    200    const double w[3],
    201    double dir[3],
    202    double* pdf)
    203 {
    204   (void)phase, (void)rng, (void)w, (void)dir, (void)pdf;
    205 }
    206 
    207 static double
    208 phase_dummy_eval
    209   (void* phase,
    210    const double wo[3],
    211    const double wi[3])
    212 {
    213   (void)phase, (void)wo, (void)wi;
    214   return 0.0;
    215 }
    216 
    217 static double
    218 phase_dummy_pdf
    219   (void* phase,
    220    const double wo[3],
    221    const double wi[3])
    222 {
    223   (void)phase, (void)wo, (void)wi;
    224   return 0.0;
    225 }
    226 
    227 static const struct ssf_phase_type phase_dummy = {
    228   phase_dummy_init,
    229   phase_dummy_release,
    230   phase_dummy_sample,
    231   phase_dummy_eval,
    232   phase_dummy_pdf,
    233   0, 1
    234 };
    235 
    236 /*******************************************************************************
    237  * Miscellaneous functions
    238  ******************************************************************************/
    239 static INLINE void
    240 check_microfacet_distribution
    241   (struct ssf_microfacet_distribution* distrib,
    242    struct ssp_rng* rng)
    243 {
    244   double N[3];
    245   const size_t NSTEPS = 10000;
    246   size_t i;
    247   size_t n;
    248   double sample[3];
    249   double E, V, SE;
    250   double sum, sum2;
    251 
    252   N[0] = ssp_rng_uniform_double(rng, -1, 1);
    253   N[1] = ssp_rng_uniform_double(rng, -1, 1);
    254   N[2] = ssp_rng_uniform_double(rng, -1, 1);
    255   d3_normalize(N, N);
    256 
    257   /* Check that D(wh) is normalized wrt \int_{2PI} D(wh) |wh.n| dwh */
    258   sum = sum2 = 0;
    259   n = 0;
    260   do {
    261     FOR_EACH(i, 0, NSTEPS) {
    262       double wh[3], pdf, D, weight;
    263       ssp_ran_hemisphere_cos(rng, N, sample, &pdf);
    264       d3_set(wh, sample);
    265       D = ssf_microfacet_distribution_eval(distrib, N, wh);
    266       weight = D * d3_dot(wh, N) / pdf;
    267       sum += weight;
    268       sum2 += weight*weight;
    269     }
    270     n += NSTEPS;
    271     E = sum / (double)n;
    272     V = MMAX(sum2 / (double)n - E*E, 0);
    273     SE = sqrt(V/(double)n);
    274   } while(SE > E * 0.05);
    275   CHK(eq_eps(E, 1.0, 3*SE) == 1);
    276 
    277   /* Check the sampling of a direction wh and the returned pdf */
    278   FOR_EACH(i, 0, NSTEPS) {
    279     double wh[3], pdf, D, weight;
    280 
    281     ssf_microfacet_distribution_sample(distrib, rng, N, wh, &pdf);
    282     D = ssf_microfacet_distribution_eval(distrib, N, wh);
    283     weight = D * d3_dot(wh, N) / pdf;
    284     CHK(eq_eps(weight, 1.0, 1.e-6) == 1);
    285     CHK(eq_eps(pdf, ssf_microfacet_distribution_pdf(distrib, N, wh), 1.e-6f));
    286 
    287     ssf_microfacet_distribution_sample(distrib, rng, N, wh, NULL);
    288   }
    289 }
    290 
    291 static INLINE void
    292 check_memory_allocator(struct mem_allocator* allocator)
    293 {
    294   if(MEM_ALLOCATED_SIZE(allocator)) {
    295     char dump[512];
    296     MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char));
    297     fprintf(stderr, "%s\n", dump);
    298     FATAL("Memory leaks\n");
    299   }
    300 }
    301 
    302 #endif /* TEST_SSF_UTILS_H */
    303