star-sf

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

ssf_microfacet_distribution.c (4652B)


      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_microfacet_distribution_c.h"
     18 
     19 #include <rsys/double3.h>
     20 #include <rsys/mem_allocator.h>
     21 #include <rsys/ref_count.h>
     22 
     23 #include <string.h>
     24 
     25 /*******************************************************************************
     26  * Helper functions
     27  ******************************************************************************/
     28 static INLINE int
     29 check_microfacet_distribution_type
     30   (const struct ssf_microfacet_distribution_type* type)
     31 {
     32   return type
     33       && type->sample
     34       && type->eval
     35       && type->pdf
     36       && IS_POW2(type->alignof_distribution);
     37 }
     38 
     39 static void
     40 microfacet_distribution_release(ref_T* ref)
     41 {
     42   struct ssf_microfacet_distribution* distrib =
     43     CONTAINER_OF(ref, struct ssf_microfacet_distribution, ref);
     44   ASSERT(ref);
     45   if(distrib->data) {
     46     if(distrib->type.release) distrib->type.release(distrib->data);
     47     MEM_RM(distrib->allocator, distrib->data);
     48   }
     49   MEM_RM(distrib->allocator, distrib);
     50 }
     51 
     52 /*******************************************************************************
     53  * Exported functions
     54  ******************************************************************************/
     55 res_T
     56 ssf_microfacet_distribution_create
     57   (struct mem_allocator* allocator,
     58    const struct ssf_microfacet_distribution_type* type,
     59    struct ssf_microfacet_distribution** out_distrib)
     60 {
     61   struct mem_allocator* mem_allocator = NULL;
     62   struct ssf_microfacet_distribution* distrib = NULL;
     63   res_T res = RES_OK;
     64 
     65   if(!out_distrib || !check_microfacet_distribution_type(type)) {
     66     res = RES_BAD_ARG;
     67     goto error;
     68   }
     69   mem_allocator = allocator ? allocator : &mem_default_allocator;
     70   distrib = MEM_CALLOC
     71     (mem_allocator, 1, sizeof(struct ssf_microfacet_distribution));
     72   if(!distrib) {
     73     res = RES_MEM_ERR;
     74     goto error;
     75   }
     76   ref_init(&distrib->ref);
     77   distrib->allocator = mem_allocator;
     78   distrib->type = *type;
     79 
     80   if(distrib->type.sizeof_distribution) {
     81     distrib->data = MEM_ALLOC_ALIGNED
     82       (distrib->allocator,
     83        distrib->type.sizeof_distribution,
     84        distrib->type.alignof_distribution);
     85     if(!distrib->data) {
     86       res = RES_MEM_ERR;
     87       goto error;
     88     }
     89     memset(distrib->data, 0, distrib->type.sizeof_distribution);
     90     if(distrib->type.init) {
     91       res = distrib->type.init(mem_allocator, distrib->data);
     92       if(res != RES_OK) goto error;
     93     }
     94   }
     95 
     96 exit:
     97   if(out_distrib) *out_distrib = distrib;
     98   return res;
     99 error:
    100   if(distrib) {
    101     SSF(microfacet_distribution_ref_put(distrib));
    102     distrib = NULL;
    103   }
    104   goto exit;
    105 }
    106 
    107 res_T
    108 ssf_microfacet_distribution_ref_get(struct ssf_microfacet_distribution* distrib)
    109 {
    110   if(!distrib) return RES_BAD_ARG;
    111   ref_get(&distrib->ref);
    112   return RES_OK;
    113 }
    114 
    115 res_T
    116 ssf_microfacet_distribution_ref_put(struct ssf_microfacet_distribution* distrib)
    117 {
    118   if(!distrib) return RES_BAD_ARG;
    119   ref_put(&distrib->ref, microfacet_distribution_release);
    120   return RES_OK;
    121 }
    122 
    123 void
    124 ssf_microfacet_distribution_sample
    125   (struct ssf_microfacet_distribution* distrib,
    126    struct ssp_rng* rng,
    127    const double N[3],
    128    double wh[3],
    129    double* out_pdf)
    130 {
    131   ASSERT(distrib && rng && N && wh);
    132   ASSERT(d3_is_normalized(N));
    133   distrib->type.sample(distrib->data, rng, N, wh, out_pdf);
    134 }
    135 
    136 double
    137 ssf_microfacet_distribution_eval
    138   (struct ssf_microfacet_distribution* distrib,
    139    const double N[3],
    140    const double wh[3])
    141 {
    142   ASSERT(distrib && N && wh);
    143   ASSERT(d3_is_normalized(N) && d3_is_normalized(wh));
    144   return distrib->type.eval(distrib->data, N, wh);
    145 }
    146 
    147 double
    148 ssf_microfacet_distribution_pdf
    149   (struct ssf_microfacet_distribution* distrib,
    150    const double N[3],
    151    const double wh[3])
    152 {
    153   ASSERT(distrib && wh );
    154   ASSERT(d3_is_normalized(N) && d3_is_normalized(wh));
    155   return distrib->type.pdf(distrib->data, N, wh);
    156 }
    157 
    158 res_T
    159 ssf_microfacet_distribution_get_data
    160   (struct ssf_microfacet_distribution* distrib, void** data)
    161 {
    162   if(!distrib || !data) return RES_BAD_ARG;
    163   *data = distrib->data;
    164   return RES_OK;
    165 }
    166