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


      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 SSF_H
     17 #define SSF_H
     18 
     19 #include <rsys/rsys.h>
     20 #include <float.h>
     21 
     22 /* Library symbol management */
     23 #if defined(SSF_SHARED_BUILD) /* Build shared library */
     24   #define SSF_API extern EXPORT_SYM
     25 #elif defined(SSF_STATIC_BUILD) /* Use/build static library */
     26   #define SSF_API extern LOCAL_SYM
     27 #else /* Use shared library */
     28   #define SSF_API extern IMPORT_SYM
     29 #endif
     30 
     31 /* Helper macro that asserts if the invocation of the ssf function `Func'
     32  * returns an error. */
     33 #ifndef NDEBUG
     34   #define SSF(Func) ASSERT(ssf_##Func == RES_OK)
     35 #else
     36   #define SSF(Func) ssf_##Func
     37 #endif
     38 
     39 /* Max value of the exponent parameter in the Blinn microfacet distribution */
     40 #define SSF_BLINN_DISTRIBUTION_MAX_EXPONENT 10000.0
     41 
     42 /* Forward declaration */
     43 struct mem_allocator;
     44 struct ssp_rng;
     45 
     46 /* Opaque data types */
     47 struct ssf_bsdf; /* Bidirectional Scattering Distribution Function */
     48 struct ssf_fresnel; /* Equation of the Fresnel term */
     49 struct ssf_microfacet_distribution;
     50 struct ssf_phase; /* Phase function */
     51 
     52 enum ssf_bxdf_flag {
     53   SSF_REFLECTION = BIT(0),
     54   SSF_TRANSMISSION = BIT(1),
     55   SSF_SPECULAR = BIT(2),
     56   SSF_DIFFUSE = BIT(3),
     57   SSF_GLOSSY = BIT(4)
     58 };
     59 
     60 enum ssf_simd {
     61   SSF_SIMD_NONE,
     62   SSF_SIMD_128,
     63   SSF_SIMD_256
     64 };
     65 
     66 /* Generic BSDF type descriptor. Note that by convention the outgoing direction
     67  * `wo' and the incoming direction `wi' point outward the surface. Furthermore,
     68  * `wo' and the normal N must point on the same side of the surface. As a
     69  * consequence the reflected or refracted direction `wi' must point on the same
     70  * side or on the opposite side of `N', respectively. */
     71 struct ssf_bsdf_type {
     72   res_T (*init)(struct mem_allocator* allocator, void* bsdf); /* Can be NULL */
     73   void (*release)(void* bsdf); /* Can be NULL */
     74 
     75   /* Sample a direction `wi' wrt `wo' whose pdf is BSDF(wo, wi) |wi.n|. Return
     76    * the value of BSDF(wo, wi) */
     77   double
     78   (*sample)
     79     (void* bsdf,
     80      struct ssp_rng* rng, /* Random number generator */
     81      const double wo[3], /* Normalized outgoing direction */
     82      const double N[3], /* Normalized surface normal */
     83      double wi[3], /* Sampled normalized incoming direction */
     84      int* type, /* Sampled component. Combination of ssf_bxdf_flag. Can be NULL */
     85      double* pdf); /* PDF to sample wi wrt wo. Can be NULL */
     86 
     87   /* Evaluate the BxDF wrt `wo' and `wi' */
     88   double
     89   (*eval)
     90     (void* bsdf,
     91      const double wo[3], /* Normalized outgoing direction */
     92      const double N[3], /* Normalized surface normal */
     93      const double wi[3]);/* Normalized incoming direction */
     94 
     95   /* Probability density function */
     96   double
     97   (*pdf)
     98     (void* bsdf,
     99      const double wo[3], /* Normalized outgoing direction */
    100      const double N[3], /* Normalized surface normal */
    101      const double wi[3]);/* Normalized incoming direction */
    102 
    103   size_t sizeof_bsdf; /* In Bytes */
    104   size_t alignof_bsdf; /* In Bytes. Must be a power of 2 */
    105 };
    106 #define SSF_BSDF_TYPE_NULL__ {NULL, NULL, NULL, NULL, NULL, 0, 1}
    107 static const struct ssf_bsdf_type SSF_BXDF_TYPE_NULL = SSF_BSDF_TYPE_NULL__;
    108 
    109 /* Generic Fresnel term descriptor */
    110 struct ssf_fresnel_type {
    111   res_T (*init)(struct mem_allocator* allocator, void* fresnel); /* Can be NULL */
    112   void (*release)(void* bxdf); /* Can be NULL */
    113 
    114   double
    115   (*eval)
    116     (void* fresnel,
    117      const double cos_wi_N); /* Cosine between facet normal and incoming dir */
    118 
    119   size_t sizeof_fresnel; /* In Bytes */
    120   size_t alignof_fresnel; /* In Bytes. Must be a power of 2 */
    121 };
    122 #define SSF_FRESNEL_TYPE_NULL__ {NULL, NULL, NULL, 0, 1}
    123 static const struct ssf_fresnel_type SSF_FRESNEL_TYPE_NULL =
    124   SSF_FRESNEL_TYPE_NULL__;
    125 
    126 /* Generic descriptor of a microfacet distribution */
    127 struct ssf_microfacet_distribution_type {
    128   res_T (*init)(struct mem_allocator* allocator, void* distrib); /* Can be NULL */
    129   void (*release)(void* distrib); /* Can be NULL */
    130 
    131   void
    132   (*sample)
    133     (void* distrib,
    134      struct ssp_rng* rng, /* Random number generator */
    135      const double N[3], /* Normalized Z-direction of the distribution */
    136      double wh[3], /* Sampled normalized half vector */
    137      double* pdf); /* PDF to sample wh. Can be NULL */
    138 
    139   double
    140   (*eval)
    141     (void* distrib,
    142      const double N[3], /* Normalized Z-direction of the distribution */
    143      const double wh[3]); /* Normalized half vector */
    144 
    145   double
    146   (*pdf)
    147     (void* distrib,
    148      const double N[3], /* Normalized Z-direction of the distribution */
    149      const double wh[3]); /* Normalized half vector */
    150 
    151   size_t sizeof_distribution; /* In Bytes */
    152   size_t alignof_distribution; /* In Bytes. Must be a Power of 2 */
    153 };
    154 #define SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__ \
    155   {NULL, NULL, NULL, NULL, NULL, 0, 1}
    156 static const struct ssf_microfacet_distribution_type
    157 SSF_MICROFACET_DISTRIBUTION_TYPE_NULL = SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__;
    158 
    159 /* Generic phase function type descriptor. Note that by convention the outgoing
    160  * direction `wo' and the incoming direction `wi' point *OUTWARD* the scattering
    161  * point. The scattering angle is thus acos(-wo.wi) */
    162 struct ssf_phase_type {
    163   res_T (*init)(struct mem_allocator* allocator, void* phase); /*Can be NULL*/
    164   void (*release)(void* phase); /* Can be NULL */
    165 
    166   /* Sample a direction `wi' wrt `wo'. */
    167   void
    168   (*sample)
    169     (void* phase,
    170      struct ssp_rng* rng, /* Random number generator */
    171      const double wo[3], /* Normalized outgoing direction */
    172      double wi[3], /* Sampled normalized incoming direction */
    173      double* pdf); /* PDF to sample wi wrt wo. Can be NULL */
    174 
    175   /* Evaluate the phase function wrt `wo' and `wi' */
    176   double
    177   (*eval)
    178     (void* phase,
    179      const double wo[3], /* Normalized outgoing direction */
    180      const double wi[3]); /* Normalized incoming direction */
    181 
    182   /* Probability density function */
    183   double
    184   (*pdf)
    185     (void* phase,
    186      const double wo[3], /* Normalized outgoing direction */
    187      const double wi[3]); /* Normalized incoming direction */
    188 
    189   size_t sizeof_phase; /* In Bytes */
    190   size_t alignof_phase; /* In Bytes. Must be a power of 2 */
    191 };
    192 #define SSF_PHASE_TYPE_NULL__ {NULL,NULL,NULL,NULL,NULL,0,1}
    193 static const struct ssf_phase_type SSF_PHASE_TYPE_NULL = SSF_PHASE_TYPE_NULL__;
    194 
    195 struct ssf_info {
    196   /* Define the supported SIMD instruction sets */
    197   char simd_128;
    198   char simd_256;
    199 };
    200 #define SSF_INFO_NULL__ {0,0}
    201 static const struct ssf_info SSF_INFO_NULL = SSF_INFO_NULL__;
    202 
    203 /* RDGFA phase function input arguments */
    204 struct ssf_phase_rdgfa_setup_args {
    205   double wavelength; /* In nm */
    206   double fractal_dimension;  /* No unit */
    207   double gyration_radius; /* In nm */
    208 
    209   /* Number of #intervals to use to discretize the angular domain */
    210   size_t nintervals;
    211 
    212   enum ssf_simd simd; /* SIMD instruction sets to use */
    213 };
    214 #define SSF_PHASE_RDGFA_SETUP_ARGS_DEFAULT__ {0,0,0,1000,SSF_SIMD_NONE}
    215 static const struct ssf_phase_rdgfa_setup_args
    216 SSF_PHASE_RDGFA_SETUP_ARGS_DEFAULT = SSF_PHASE_RDGFA_SETUP_ARGS_DEFAULT__;
    217 
    218 struct ssf_phase_rdgfa_desc {
    219   double wavelength; /* In nm */
    220   double fractal_dimension;  /* No unit */
    221   double gyration_radius; /* In nm */
    222 
    223   double normalization_factor; /* Normalization factor of the cumulative */
    224   size_t nintervals; /* #intervals used to discretized the cumulative */
    225 };
    226 #define SSF_PHASE_RDGFA_DESC_NULL__ {0,0,0,0,0}
    227 static const struct ssf_phase_rdgfa_desc SSF_PHASE_RDGFA_DESC_NULL =
    228   SSF_PHASE_RDGFA_DESC_NULL__;
    229 
    230 struct ssf_phase_rdgfa_interval {
    231   double range[2]; /* Angular range of the interval. In rad */
    232   double cumulative; /* Value of the cumulative of the interval */
    233 };
    234 #define SSF_PHASE_RDGFA_INTERVAL_NULL__ {{DBL_MAX,-DBL_MAX}, 0}
    235 static const struct ssf_phase_rdgfa_interval SSF_PHASE_RDGFA_INTERVAL_NULL =
    236   SSF_PHASE_RDGFA_INTERVAL_NULL__;
    237 
    238 struct ssf_discrete_item {
    239   double theta; /* In radian */
    240   double value;
    241 };
    242 #define SSF_DISCRETE_ITEM_NULL__ {0,0}
    243 static const struct ssf_discrete_item SSF_DISCRETE_ITEM_NULL =
    244   SSF_DISCRETE_ITEM_NULL__;
    245 
    246 /* Discrete phase function input arguments */
    247 struct ssf_discrete_setup_args {
    248   void (*get_item) /* Returns a given discrete item */
    249     (const size_t iitem,
    250      struct ssf_discrete_item* item,
    251      void* context);
    252   void* context; /* User defined data sent to `get_item' functor */
    253   size_t nitems; /* #discrete items */
    254 };
    255 #define SSF_DISCRETE_SETUP_ARGS_NULL__ {NULL,NULL,0}
    256 static const struct ssf_discrete_setup_args
    257 SSF_DISCRETE_SETUP_ARGS_NULL = SSF_DISCRETE_SETUP_ARGS_NULL__;
    258 
    259 BEGIN_DECLS
    260 
    261 /*******************************************************************************
    262  * Built-in BSDFs
    263  ******************************************************************************/
    264 /* Dirac distribution whose incoming direction `wi' is the reflection of the
    265  * supplied direction `wo' with respect to the surface normal `N'. The
    266  * directional reflectance is controlled by the Fresnel term `Fr'.
    267  *    fr(wo, wi) = Fr(|wi.N|) * delta(wo - Reflect(wi, N)) / |wi.N|
    268  * Since it is a dirac distribution, the returned value of the `eval' and `pdf'
    269  * function is always 0 while the pdf returned by `sample' function is
    270  * infinity. */
    271 SSF_API const struct ssf_bsdf_type ssf_specular_reflection;
    272 
    273 /* Reflects the same intensity in all direction independently of the incoming
    274  * direction; fr(wo, wr) = R/PI */
    275 SSF_API const struct ssf_bsdf_type ssf_lambertian_reflection;
    276 
    277 /* Glossy reflections with respect to a microfacet distribution. It is based on
    278  * the Torrance Sparrow BRDF to provide a general Microfacet-based BRDF model
    279  *    fr(wo, wi) = Fr(|wi.wh|) * G(wo, wi) * D(wh) / (4 * |wo.N| * |wi.N|)
    280  * with `wh' the half vector between `wi' and `wo', `Fr(|wi.wh|)' the Fresnel
    281  * term that controls the directional reflectance, `G(wo, wi)' the geometric
    282  * attenuation term that describes the masking and the shadowing of the
    283  * microfacets and `D(wh)' the distribution area of the microfacets whose
    284  * normal is `wh'. Note that common BRDFs based on this model ignore multiple
    285  * scattering of lights into the microfacet structure and remove them with the
    286  * 'G' term. As a consequence, this model does not satisfy the energy
    287  * conservation property */
    288 SSF_API const struct ssf_bsdf_type ssf_microfacet_reflection;
    289 
    290 /* Glossy reflections with respect to a microfacet distribution. In contrast to
    291  * the ssp_microfacet_reflection model, this BRDF ensures, by design, the
    292  * energy conservation property without requiring the normalization of the
    293  * BRDF. As a counterpart, it only provides the sample function. The others
    294  * functions return invalid value. However, it is well suited for Monte Carlo
    295  * integrations that only need to sample a direction and to define its
    296  * associated directional reflectance */
    297 SSF_API const struct ssf_bsdf_type ssf_microfacet2_reflection;
    298 
    299 /* This BSDF consists in a model of refraction effects within a thin slab of a
    300  * dielectric material, combine with a dirac distribution of the reflection at
    301  * the interfaces as provided by ssf_specular_reflection. Global reflection (R),
    302  * absorption (A) and transmission (T) parameters are computed from the
    303  * infinite series of contributions that come from multiple refraction effects
    304  * within the slab.
    305  *
    306  * Assuming a perfect dielectric material, the Fresnel term provided by
    307  * ssf_fresnel_dielectric_dielectric is used to compute "rho", i.e. the
    308  * reflected part during a single refraction event. But since real materials
    309  * are not ideal dielectrics, the slab is also supposed to absorb incoming
    310  * radiation. The absorption coefficient "alpha" of the material is provided
    311  * by the user. */
    312 SSF_API const struct ssf_bsdf_type ssf_thin_specular_dielectric;
    313 
    314 /* Dirac distribution whose incoming direction `wi' is either refracted or
    315  * reflecter wrt N and a dielectric/dielectric fresnel term `Fr'.
    316  *    f_reflected(wo, wi) = Fr(|wi.N|) * delta(wo - Reflect(wi, N)) / |wi.N|
    317  *    f_refracted(wo, wi) = (1-Fr(|wi.N|)) * delta(wo - Refract(wi, N)) / |wi.N|
    318  * Since it is a dirac distribution, the returned value of the `eval' and `pdf'
    319  * function is always 0 while the pdf returned by `sample' function is
    320  * infinity. */
    321 SSF_API const struct ssf_bsdf_type ssf_specular_dielectric_dielectric_interface;
    322 
    323 /*******************************************************************************
    324  * Built-in Fresnel terms
    325  ******************************************************************************/
    326 /* Fresnel term is a constant; Fr = k with k in [0, 1]. */
    327 SSF_API const struct ssf_fresnel_type ssf_fresnel_constant;
    328 
    329 /* Fresnel term for perfect reflection; Fr = 1 */
    330 SSF_API const struct ssf_fresnel_type ssf_fresnel_no_op;
    331 
    332 /* Fresnel term between 2 dielectric mediums.
    333  *    Fr = 1/2 * (Rs^2 + Rp^2)
    334  * with `Rs' and `Rp' the reflectance for the light polarized with its electric
    335  * field perpendicular or parallel to the plane of incidence, respectively.
    336  *    Rs = (n1*|wi.N| - n2*|wt.N|) / (n1*|wi.N| + n2*|wt.N)
    337  *    Rp = (n2*|wi.N| - n1*|wt.N|) / (n2*|wi.N| + n1*|wt.N)
    338  * with `n1' and `n2' the indices of refraction of the incident and transmitted
    339  * media, and `wi' and `wt' the incident and transmitted direction. */
    340 SSF_API const struct ssf_fresnel_type ssf_fresnel_dielectric_dielectric;
    341 
    342 /* Fresnel term between a dielectric and a conductor.
    343  *    Fr = 1/2 * (Rs^2 + Rp^2)
    344  * with `Rs' and `Rp' the reflectance for the light polarized with its electric
    345  * field perpendicular or parallel to the plane of incidence, respectively.
    346  *    Rs = (n1*|wi.N| - (n2 - i*k2)*|wt.N|) / (n1*|wi.N| + (n2 - i*k2)*|wt.N|)
    347  *    Rp = ((n2 - i*k2)*|wt.N| - n1*|wi.N|) / ((n2 - i*k2)*|wt.N| + n1*|wi.N|)
    348  * with `n1' the index of refraction of the incident media, `n2' and `k2' the
    349  * real and imaginary part of the index of refraction of the transmitted media,
    350  * and `wi' and `wt' the incident and transmitted direction */
    351 SSF_API const struct ssf_fresnel_type ssf_fresnel_dielectric_conductor;
    352 
    353 /*******************************************************************************
    354  * Built-in microfacet distributions
    355  ******************************************************************************/
    356 /* Beckmann microfacet distribution.
    357  *    D(wh) = exp(-tan^2(a)/m^2) / (PI*m^2*cos^4(a))
    358  * with `a' = arccos(wh.N) and `m' the rougness in ]0, 1] of the surface */
    359 SSF_API const struct ssf_microfacet_distribution_type ssf_beckmann_distribution;
    360 
    361 /* Blinn microfacet distribution.
    362  *    D(wh) = (e + 2) / (2*PI) * (wh.N)^e
    363  * with `e' an exponent in [0, SSF_BLINN_DISTRIBUTION_MAX_EXPONENT] */
    364 SSF_API const struct ssf_microfacet_distribution_type ssf_blinn_distribution;
    365 
    366 /* Pillbox microfacet distribution.
    367  *            | 0; if |wh.N| >= m
    368  *    D(wh) = | 1 / (PI * (1 - cos^2(m))); if |wh.N| < m
    369  * with `m' the roughness parameter in ]0, 1] */
    370 SSF_API const struct ssf_microfacet_distribution_type ssf_pillbox_distribution;
    371 
    372 /*******************************************************************************
    373  * Built-in phase functions.
    374  ******************************************************************************/
    375 /* Henyey & Greenstein phase function normalized to 1; p(wo, wi) == pdf(wo, wi).
    376  *    p(wo, wi) = 1/(4*PI)* (1-g^2) / (1+g^2-2*g*(-wo.wi))^3/2 */
    377 SSF_API const struct ssf_phase_type ssf_phase_hg;
    378 
    379 /* Rayleigh phase function normalized to 1; p(wo, wi) == pdf(wo, wi).
    380  *    p(wo, wi) = 3/(16*PI) * (1+(-wo.wi)^2) */
    381 SSF_API const struct ssf_phase_type ssf_phase_rayleigh;
    382 
    383 /* RDGFA phase function normalized to 1:
    384  *    p(wo, wi) = 3/(16*PI) * f(theta)/g * (1+cos(theta)^2);
    385  *    theta = acos(wo.wi)
    386  *
    387  * "Effects of multiple scattering on radiative properties of soot fractal
    388  * aggregates" J. Yon et al., Journal of Quantitative Spectroscopy and
    389  * Radiative Transfer Vol 133, pp. 374-381, 2014 */
    390 SSF_API const struct ssf_phase_type ssf_phase_rdgfa;
    391 
    392 /* Discrete phase function normalized to 1 */
    393 SSF_API const struct ssf_phase_type ssf_phase_discrete;
    394 
    395 /*******************************************************************************
    396  * SSF API
    397  ******************************************************************************/
    398 SSF_API res_T
    399 ssf_get_info
    400   (struct ssf_info* info);
    401 
    402 /*******************************************************************************
    403  * BSDF API - Bidirectional Scattering Distribution Function. Describes the way
    404  * the light is scattered by a surface. Note that by convention the outgoing
    405  * direction `wo' and the incoming direction `wi' point outward the surface.
    406  * Furthermore, `wo' and the normal `N' must point on the same side of the
    407  * surface. As a consequence the reflected or refracted direction `wi' must
    408  * point on the same side or on the opposite side of `N', respectively.
    409  ******************************************************************************/
    410 SSF_API res_T
    411 ssf_bsdf_create
    412   (struct mem_allocator* allocator, /* May be NULL <=> Use default allocator */
    413    const struct ssf_bsdf_type* type,
    414    struct ssf_bsdf** bsdf);
    415 
    416 SSF_API res_T
    417 ssf_bsdf_ref_get
    418   (struct ssf_bsdf* bsdf);
    419 
    420 SSF_API res_T
    421 ssf_bsdf_ref_put
    422   (struct ssf_bsdf* bsdf);
    423 
    424 /* Sample a direction `wi' wrt `wo' whose pdf is BSDF(wo, wi) |wi.n|. Return
    425  * the directional reflectance, i.e. pdf to be reflected in *any* direction
    426  * wrt to the incident direction `wi' */
    427 SSF_API double
    428 ssf_bsdf_sample
    429   (struct ssf_bsdf* bsdf,
    430    struct ssp_rng* rng, /* Random number generator */
    431    const double wo[3], /* Normalized outgoing direction */
    432    const double N[3], /* Normalized surface normal */
    433    double wi[3], /* Sampled normalized incoming direction */
    434    int* type, /* Type of the sampled component. Combination of ssf_bxdf_flag */
    435    double* pdf); /* PDF to sample wi wrt wo */
    436 
    437 SSF_API double
    438 ssf_bsdf_eval
    439   (struct ssf_bsdf* bsdf,
    440    const double wo[3], /* Normalized outgoing direction */
    441    const double N[3], /* Normalized surface normal */
    442    const double wi[3]); /* Normalized incoming direction */
    443 
    444 SSF_API double /* Probability density function*/
    445 ssf_bsdf_pdf
    446   (struct ssf_bsdf* bsdf,
    447    const double wo[3], /* Normalized outgoing direction */
    448    const double N[3], /* Normalized surface normal */
    449    const double wi[3]); /* Normalized incoming direction */
    450 
    451 SSF_API res_T
    452 ssf_bsdf_get_data
    453   (struct ssf_bsdf* bsdf,
    454    void** data);
    455 
    456 SSF_API res_T
    457 ssf_specular_reflection_setup
    458   (struct ssf_bsdf* bsdf,
    459    struct ssf_fresnel* fresnel);
    460 
    461 SSF_API res_T
    462 ssf_lambertian_reflection_setup
    463   (struct ssf_bsdf* bsdf,
    464    const double reflectivity);
    465 
    466 SSF_API res_T
    467 ssf_microfacet_reflection_setup
    468   (struct ssf_bsdf* bsdf,
    469    struct ssf_fresnel* fresnel,
    470    struct ssf_microfacet_distribution* distrib);
    471 
    472 SSF_API res_T
    473 ssf_thin_specular_dielectric_setup
    474   (struct ssf_bsdf* bsdf,
    475    const double absorption, /* In [0, 1] */
    476    const double eta_i, /* Refraction id of the medium the ray travels in */
    477    const double eta_t, /* Refraction id of the thin dielectric slab */
    478    const double thickness); /* Thickness of the slab */
    479 
    480 SSF_API res_T
    481 ssf_specular_dielectric_dielectric_interface_setup
    482   (struct ssf_bsdf* bsdf,
    483    const double eta_i,
    484    const double eta_t);
    485 
    486 /*******************************************************************************
    487  * Phase function API - Describes the way the light is scattered in a medium.
    488  * Note that by convention the outgoing direction `wo' and the incoming
    489  * direction `wi' point outward the scattering position.
    490  ******************************************************************************/
    491 SSF_API res_T
    492 ssf_phase_create
    493   (struct mem_allocator* allocator, /* May be NULL <=> Use default allocator */
    494    const struct ssf_phase_type* type,
    495    struct ssf_phase** phase);
    496 
    497 SSF_API res_T
    498 ssf_phase_ref_get
    499   (struct ssf_phase* phase);
    500 
    501 SSF_API res_T
    502 ssf_phase_ref_put
    503   (struct ssf_phase* phase);
    504 
    505 SSF_API void
    506 ssf_phase_sample
    507   (struct ssf_phase* phase,
    508    struct ssp_rng* rng, /* Random number generator */
    509    const double wo[3], /* Normalized outgoing direction */
    510    double wi[3], /* Sampled normalized incoming direction */
    511    double* pdf); /* PDF to sample wi wrt wo */
    512 
    513 SSF_API double
    514 ssf_phase_eval
    515   (struct ssf_phase* phase,
    516    const double wo[3], /* Normalized outgoing direction */
    517    const double wi[3]); /* Normalized incoming direction */
    518 
    519 SSF_API double
    520 ssf_phase_pdf
    521   (struct ssf_phase* phase,
    522    const double wo[3], /* Normalized outgoing direction */
    523    const double wi[3]); /* Normalized incoming direction */
    524 
    525 SSF_API res_T
    526 ssf_phase_get_data
    527   (struct ssf_phase* bsdf,
    528    void** data);
    529 
    530 SSF_API res_T
    531 ssf_phase_hg_setup
    532   (struct ssf_phase* phase,
    533    const double g); /* Asymmetric parameter in [-1, 1] */
    534 
    535 SSF_API res_T
    536 ssf_phase_discrete_setup
    537   (struct ssf_phase* phase,
    538    const struct ssf_discrete_setup_args* args);
    539 
    540 /*******************************************************************************
    541  * RDGFA phase function
    542  ******************************************************************************/
    543 SSF_API res_T
    544 ssf_phase_rdgfa_setup
    545   (struct ssf_phase* phase,
    546    const struct ssf_phase_rdgfa_setup_args* args);
    547 
    548 SSF_API res_T
    549 ssf_phase_rdgfa_get_desc
    550   (const struct ssf_phase* phase,
    551    struct ssf_phase_rdgfa_desc* desc);
    552 
    553 SSF_API res_T
    554 ssf_phase_rdgfa_get_interval
    555   (const struct ssf_phase* phase,
    556    const size_t interval_id, /* In [0, desc.nintervals[ */
    557    struct ssf_phase_rdgfa_interval* interval);
    558 
    559 /*******************************************************************************
    560  * Fresnel API - Define the equation of the fresnel term
    561  ******************************************************************************/
    562 SSF_API res_T
    563 ssf_fresnel_create
    564   (struct mem_allocator* allocator,
    565    const struct ssf_fresnel_type* type,
    566    struct ssf_fresnel** fresnel);
    567 
    568 SSF_API res_T
    569 ssf_fresnel_ref_get
    570   (struct ssf_fresnel* fresnel);
    571 
    572 SSF_API res_T
    573 ssf_fresnel_ref_put
    574   (struct ssf_fresnel* fresnel);
    575 
    576 SSF_API double
    577 ssf_fresnel_eval
    578   (struct ssf_fresnel* fresnel,
    579    const double cos_theta); /* Cos between facet normal and incoming dir */
    580 
    581 /* Retrieve the internal data of the Fresnel term. Usefull for user defined
    582  * Fresnel terms on which the caller has to retrieve their data to setup the
    583  * parameters of their Fresnel equation. */
    584 SSF_API res_T
    585 ssf_fresnel_get_data
    586   (struct ssf_fresnel* fresnel,
    587    void** data);
    588 
    589 SSF_API res_T
    590 ssf_fresnel_dielectric_dielectric_setup
    591   (struct ssf_fresnel* fresnel,
    592    /* Refraction id of the medium the incoming ray travels in */
    593    const double eta_i,
    594    /* Refraction id of the medium the outgoing transmission ray travels in */
    595    const double eta_t);
    596 
    597 SSF_API res_T
    598 ssf_fresnel_dielectric_conductor_setup
    599   (struct ssf_fresnel* fresnel,
    600    const double eta_i, /* Refraction id of the dielectric medium */
    601    const double eta_t, /* Real part of the refraction id of the conductor */
    602    const double k_t); /* Imaginary part of the refraction id of the conductor */
    603 
    604 SSF_API res_T
    605 ssf_fresnel_constant_setup
    606   (struct ssf_fresnel* fresnel,
    607    const double constant); /* in [0, 1] */
    608 
    609 /*******************************************************************************
    610  * Microfacet Distribution API - Note that by convention the outgoing direction
    611  * `wo' and the half vector `wh' point outward the surface.
    612  ******************************************************************************/
    613 SSF_API res_T
    614 ssf_microfacet_distribution_create
    615   (struct mem_allocator* allocator,
    616    const struct ssf_microfacet_distribution_type* type,
    617    struct ssf_microfacet_distribution** distrib);
    618 
    619 SSF_API res_T
    620 ssf_microfacet_distribution_ref_get
    621   (struct ssf_microfacet_distribution* distrib);
    622 
    623 SSF_API res_T
    624 ssf_microfacet_distribution_ref_put
    625   (struct ssf_microfacet_distribution* distrib);
    626 
    627 SSF_API double
    628 ssf_microfacet_distribution_eval
    629   (struct ssf_microfacet_distribution* distrib,
    630    const double N[3], /* Normalized Z-direction of the distribution */
    631    const double wh[3]); /* Normalized half vector */
    632 
    633 SSF_API void
    634 ssf_microfacet_distribution_sample
    635   (struct ssf_microfacet_distribution* distrib,
    636    struct ssp_rng* rng, /* Random number generator */
    637    const double N[3], /* Normalized Z-direction of the distribution */
    638    double wh[3], /* Normalized half vector */
    639    double* pdf); /* PDF of the sampled half vector */
    640 
    641 SSF_API double
    642 ssf_microfacet_distribution_pdf
    643   (struct ssf_microfacet_distribution* distrib,
    644    const double N[3], /* Normalized Z-direction of the distribution */
    645    const double wh[3]); /* Normalized half vector */
    646 
    647 /* Retrieve the internal data of the microfacet distribution. Usefull for user
    648  * defined distributions on which the caller has to retrieve their data to
    649  * setup their parameters. */
    650 SSF_API res_T
    651 ssf_microfacet_distribution_get_data
    652   (struct ssf_microfacet_distribution* distrib,
    653    void** data);
    654 
    655 SSF_API res_T
    656 ssf_beckmann_distribution_setup
    657   (struct ssf_microfacet_distribution* distrib,
    658    const double roughness); /* In ]0, 1] */
    659 
    660 SSF_API res_T
    661 ssf_blinn_distribution_setup
    662   (struct ssf_microfacet_distribution* distrib,
    663    const double exponent); /* in [0, SSF_BLINN_DISTRIBUTION_MAX_EXPONENT] */
    664 
    665 SSF_API res_T
    666 ssf_pillbox_distribution_setup
    667   (struct ssf_microfacet_distribution* distrib,
    668    const double roughness); /* In ]0, 1] */
    669 
    670 END_DECLS
    671 
    672 #endif /* SSF_H */