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 46e0e9b89ecbd6afb1287ecc623dab288b5ddda4
parent 4fe8e6e919eafceb6473491e755e67e3d3c30975
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 18 Jul 2018 16:49:10 +0200

Test the Henyey & Greenstein phase function

Diffstat:
Mcmake/CMakeLists.txt | 1+
Asrc/test_ssf_phase_hg.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_ssf_utils.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -116,6 +116,7 @@ if(NOT NO_TEST) new_test(test_ssf_microfacet_distribution) new_test(test_ssf_microfacet_reflection) new_test(test_ssf_phase) + new_test(test_ssf_phase_hg) new_test(test_ssf_specular_reflection) new_test(test_ssf_thin_specular_dielectric) diff --git a/src/test_ssf_phase_hg.c b/src/test_ssf_phase_hg.c @@ -0,0 +1,83 @@ +/* Copyright (C) |Meso|Star> 2016-2018 (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 "test_ssf_utils.h" + +#define NG 10 +#define NSAMPS 10000 + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct ssf_phase* phase; + struct ssf_phase* dummy; + struct ssp_rng* rng; + size_t i; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK); + + CHK(ssf_phase_create(&allocator, &ssf_phase_hg, &phase) == RES_OK); + CHK(ssf_phase_create(&allocator, &phase_dummy, &dummy) == RES_OK); + + CHK(ssf_phase_hg_setup(NULL, -2) == RES_BAD_ARG); + CHK(ssf_phase_hg_setup(phase, -2) == RES_BAD_ARG); + CHK(ssf_phase_hg_setup(NULL, -1) == RES_BAD_ARG); + CHK(ssf_phase_hg_setup(phase, -1) == RES_OK); + CHK(ssf_phase_hg_setup(phase, 0) == RES_OK); + CHK(ssf_phase_hg_setup(phase, 1) == RES_OK); + CHK(ssf_phase_hg_setup(dummy, 1) == RES_BAD_ARG); + + FOR_EACH(i, 0, NG) { + const double g = ssp_rng_uniform_double(rng, -1, +1); + double wo[3]; + double sum_cos = 0; + double sum_cos_sqr = 0; + double E, V, SE; + size_t isamp; + + CHK(ssf_phase_hg_setup(phase, g) == RES_OK); + + ssp_ran_sphere_uniform(rng, wo, NULL); + FOR_EACH(isamp, 0, NSAMPS) { + double wi[3]; + double pdf; + double w; + ssf_phase_sample(phase, rng, wo, wi, &pdf); + CHK(d3_is_normalized(wi)); + CHK(eq_eps(ssf_phase_pdf(phase, wo, wi), pdf, 1.e-6)); + w = d3_dot(wo, wi); + sum_cos += w; + sum_cos_sqr += w*w; + } + /* On average cos(wo, wi) should be g */ + E = sum_cos / NSAMPS; + V = sum_cos_sqr / NSAMPS - E*E; + SE = sqrt(V/NSAMPS); + CHK(eq_eps(sum_cos / NSAMPS, E, SE) == 1); + } + + CHK(ssf_phase_ref_put(phase) == RES_OK); + CHK(ssf_phase_ref_put(dummy) == RES_OK); + CHK(ssp_rng_ref_put(rng) == RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_ssf_utils.h b/src/test_ssf_utils.h @@ -178,6 +178,63 @@ static const struct ssf_microfacet_distribution_type microfacet_dummy = { }; /******************************************************************************* + * Dummy Phase function type + ******************************************************************************/ +static res_T +phase_dummy_init(struct mem_allocator* allocator, void* phase) +{ + (void)allocator, (void)phase; + return RES_OK; +} + +static void +phase_dummy_release(void* phase) +{ + (void)phase; +} + +static double +phase_dummy_sample + (void* phase, + struct ssp_rng* rng, + const double w[3], + double dir[3], + double* pdf) +{ + (void)phase, (void)rng, (void)w, (void)dir, (void)pdf; + return 0.0; +} + +static double +phase_dummy_eval + (void* phase, + const double wo[3], + const double wi[3]) +{ + (void)phase, (void)wo, (void)wi; + return 0.0; +} + +static double +phase_dummy_pdf + (void* phase, + const double wo[3], + const double wi[3]) +{ + (void)phase, (void)wo, (void)wi; + return 0.0; +} + +static const struct ssf_phase_type phase_dummy = { + phase_dummy_init, + phase_dummy_release, + phase_dummy_sample, + phase_dummy_eval, + phase_dummy_pdf, + 0, 1 +}; + +/******************************************************************************* * Miscellaneous functions ******************************************************************************/ static INLINE void