star-sf

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

commit ef1442447e44956317b98aa4d1fb5df702c42edb
parent 941277a1bc97837d22befd804c6de6368f099cb8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 28 Sep 2016 19:09:33 +0200

Add the Blinn Microfacet distribution

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssf.h | 9++++++++-
Asrc/ssf_blinn_distribution.c | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -52,6 +52,7 @@ set(SSF_FILES_INC ssf_optics.h) set(SSF_FILES_SRC ssf_beckmann_distribution.c + ssf_blinn_distribution.c ssf_bsdf.c ssf_bxdf.c ssf_fresnel.c diff --git a/src/ssf.h b/src/ssf.h @@ -162,8 +162,10 @@ SSF_API const struct ssf_fresnel_type ssf_fresnel_dielectric_dielectric; /* Fresnel term between a dielectric and a conductor */ SSF_API const struct ssf_fresnel_type ssf_fresnel_dielectric_conductor; -/* Beckmann microfacet distribution */ +/* Beckmann microfacet distribution TODO add comments */ SSF_API const struct ssf_microfacet_distribution_type ssf_beckmann_distribution; +/* Blinn microfacet distribution TODO add comments */ +SSF_API const struct ssf_microfacet_distribution_type ssf_blinn_distribution; /******************************************************************************* * BSDF API - Bidirectionnal Scattering Distribution Function. Describes the @@ -398,6 +400,11 @@ ssf_beckmann_distribution_setup (struct ssf_microfacet_distribution* distrib, const double roughness); /* Must be > 0 */ +SSF_API res_T +ssf_blinn_distribution_setup + (struct ssf_microfacet_distribution* distrib, + const double exponent); /* in [0, 10000] */ + END_DECLS #endif /* SSF_H */ diff --git a/src/ssf_blinn_distribution.c b/src/ssf_blinn_distribution.c @@ -0,0 +1,133 @@ +/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "ssf.h" +#include "ssf_microfacet_distribution_c.h" + +#include <rsys/double3.h> +#include <rsys/double33.h> + +#define EXPONENT_MAX 10000 + +struct blinn_distribution { + double exponent; +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static res_T +blinn_distribution_init(struct mem_allocator* allocator, void* distrib) +{ + ASSERT(distrib); + (void)allocator; + ((struct blinn_distribution*)distrib)->exponent = 32.0; + return RES_OK; +} + +static void +blinn_distribution_release(void* distrib) +{ (void)distrib; } + +static double +blinn_distribution_eval + (void* distrib, const double wo[3], const double N[3], const double wh[3]) +{ + struct blinn_distribution* blinn = distrib; + double cos_wh_N; + ASSERT(distrib && wo && N && wh); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wh)); + ASSERT(blinn->exponent >= 0.0 && blinn->exponent <= EXPONENT_MAX); + (void)wo; + cos_wh_N = d3_dot(wh, N); + return (blinn->exponent + 2) / (2*PI) * pow(cos_wh_N, blinn->exponent); +} + +static void +blinn_distribution_sample + (void* distrib, + const double u, + const double v, + const double wo[3], + const double N[3], + double wh[3], + double* pdf) +{ + struct blinn_distribution* blinn = distrib; + double basis[9]; + double dir[3]; + double cos_theta, sin_theta; + double cos_wh_wo; + double phi; + ASSERT(distrib && u>=0 && u<1 && v>=0 && v<1 && wo && N && wh && pdf); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); + + phi = v*2*PI; + cos_theta = pow(u, 1/(blinn->exponent+1)); + sin_theta = sqrt(MMAX(0, 1-cos_theta*cos_theta)); + dir[0] = cos(phi) * sin_theta; + dir[1] = sin(phi) * sin_theta; + dir[2] = cos_theta; + + d33_muld3(dir, d33_basis(basis, N), dir); + cos_wh_wo = d3_dot(dir, wo); + *pdf = cos_wh_wo > 0 + ? (blinn->exponent+1)*pow(cos_theta, blinn->exponent) / (2*PI*4*cos_wh_wo) + : 0; + d3_set(wh, dir); +} + +static double +blinn_distribution_pdf + (void* distrib, const double wo[3], const double N[3], const double wh[3]) +{ + struct blinn_distribution* blinn = distrib; + double cos_wh_N, cos_wh_wo; + ASSERT(distrib && wo && N && wh); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wh)); + cos_wh_wo = d3_dot(wo, wh); + if(cos_wh_wo <= 0) return 0.0; + cos_wh_N = fabs(d3_dot(wh, N)); + return + ((blinn->exponent+1)*pow(cos_wh_N, blinn->exponent)) / (2*PI*4*cos_wh_wo); +} + +/******************************************************************************* + * Exported symbols + ******************************************************************************/ +const struct ssf_microfacet_distribution_type ssf_blinn_distribution = { + blinn_distribution_init, + blinn_distribution_release, + blinn_distribution_sample, + blinn_distribution_eval, + blinn_distribution_pdf, + sizeof(struct blinn_distribution), + ALIGNOF(struct blinn_distribution) +}; + +res_T +ssf_blinn_distribution_setup + (struct ssf_microfacet_distribution* distrib, + const double exponent) +{ + if(!distrib || exponent < 0 || exponent > EXPONENT_MAX) + return RES_BAD_ARG; + if(!MICROFACET_DISTRIBUTION_TYPE_EQ(&distrib->type, &ssf_blinn_distribution)) + return RES_BAD_ARG; + ((struct blinn_distribution*)distrib->data)->exponent = exponent; + return RES_OK; +} + +