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_blinn_distribution.c (3717B)


      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/double33.h>
     21 
     22 #include <star/ssp.h>
     23 
     24 struct blinn_distribution {
     25   double exponent;
     26 };
     27 
     28 /*******************************************************************************
     29  * Private functions
     30  ******************************************************************************/
     31 static res_T
     32 blinn_distribution_init(struct mem_allocator* allocator, void* distrib)
     33 {
     34   ASSERT(distrib);
     35   (void)allocator;
     36   ((struct blinn_distribution*)distrib)->exponent = 32.0;
     37   return RES_OK;
     38 }
     39 
     40 static double
     41 blinn_distribution_eval(void* distrib, const double N[3], const double wh[3])
     42 {
     43   struct blinn_distribution* blinn = distrib;
     44   double cos_wh_N;
     45   ASSERT(distrib && N && wh);
     46   ASSERT(d3_is_normalized(N) && d3_is_normalized(wh));
     47   ASSERT(blinn->exponent >= 0.0);
     48   ASSERT(blinn->exponent <= SSF_BLINN_DISTRIBUTION_MAX_EXPONENT);
     49   cos_wh_N = d3_dot(wh, N);
     50   return (blinn->exponent + 2) / (2*PI) * pow(cos_wh_N, blinn->exponent);
     51 }
     52 
     53 static void
     54 blinn_distribution_sample
     55   (void* distrib,
     56    struct ssp_rng* rng,
     57    const double N[3],
     58    double wh[3],
     59    double* pdf)
     60 {
     61   struct blinn_distribution* blinn = distrib;
     62   double basis[9];
     63   double dir[3];
     64   double cos_theta, sin_theta;
     65   double phi;
     66   double u, v;
     67   ASSERT(distrib && rng && N && wh);
     68   ASSERT(d3_is_normalized(N));
     69 
     70   u = ssp_rng_canonical(rng);
     71   v = ssp_rng_canonical(rng);
     72 
     73   phi = v*2*PI;
     74   cos_theta = pow(u, 1/(blinn->exponent+1));
     75   sin_theta = sqrt(MMAX(0, 1-cos_theta*cos_theta));
     76   dir[0] = cos(phi) * sin_theta;
     77   dir[1] = sin(phi) * sin_theta;
     78   dir[2] = cos_theta;
     79 
     80   d33_muld3(dir, d33_basis(basis, N),  dir);
     81   d3_set(wh, dir);
     82 
     83   if(pdf) *pdf = (blinn->exponent+2)/(2*PI)*pow(cos_theta, blinn->exponent+1);
     84 }
     85 
     86 static double
     87 blinn_distribution_pdf(void* distrib, const double N[3], const double wh[3])
     88 {
     89   struct blinn_distribution* blinn = distrib;
     90   double cos_wh_N;
     91   ASSERT(distrib && N && wh);
     92   ASSERT(d3_is_normalized(N) && d3_is_normalized(wh));
     93   cos_wh_N = fabs(d3_dot(wh, N));
     94   return (blinn->exponent+2)/(2*PI)*pow(cos_wh_N, blinn->exponent+1);
     95 }
     96 
     97 /*******************************************************************************
     98  * Exported symbols
     99  ******************************************************************************/
    100 const struct ssf_microfacet_distribution_type ssf_blinn_distribution = {
    101   blinn_distribution_init,
    102   NULL,
    103   blinn_distribution_sample,
    104   blinn_distribution_eval,
    105   blinn_distribution_pdf,
    106   sizeof(struct blinn_distribution),
    107   ALIGNOF(struct blinn_distribution)
    108 };
    109 
    110 res_T
    111 ssf_blinn_distribution_setup
    112   (struct ssf_microfacet_distribution* distrib,
    113    const double exponent)
    114 {
    115   if(!distrib || exponent < 0 || exponent > SSF_BLINN_DISTRIBUTION_MAX_EXPONENT)
    116     return RES_BAD_ARG;
    117   if(!MICROFACET_DISTRIBUTION_TYPE_EQ(&distrib->type, &ssf_blinn_distribution))
    118     return RES_BAD_ARG;
    119   ((struct blinn_distribution*)distrib->data)->exponent = exponent;
    120   return RES_OK;
    121 }
    122 
    123