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:
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