commit 5f8c118e1ef0ff29b556aad687e2370212b1e3dd
parent 36dceabd5c342b6e83fac99ef8077a0cbdfb54c6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 28 Sep 2016 12:03:09 +0200
Test the microfacet distribution API
Diffstat:
2 files changed, 216 insertions(+), 0 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -103,6 +103,7 @@ if(NOT NO_TEST)
new_test(test_ssf_fresnel_dielectric_dielectric)
new_test(test_ssf_fresnel_no_op)
new_test(test_ssf_lambertian_reflection)
+ new_test(test_ssf_microfacet_distribution)
new_test(test_ssf_microfacet_reflection)
new_test(test_ssf_specular_reflection)
endif()
diff --git a/src/test_ssf_microfacet_distribution.c b/src/test_ssf_microfacet_distribution.c
@@ -0,0 +1,215 @@
+/* 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 "test_ssf_utils.h"
+
+#include <rsys/double3.h>
+
+static int ufacet_is_init = 0;
+
+struct ALIGN(64) ufacet {
+ uint32_t id;
+ double u;
+ double v;
+ double wh[3];
+ double wo[3];
+ double N[3];
+ double pdf;
+ double value;
+};
+
+static res_T
+ufacet_init(struct mem_allocator* allocator, void* distrib)
+{
+ NCHECK(allocator, NULL);
+ NCHECK(distrib, NULL);
+ CHECK(IS_ALIGNED(distrib, 64), 1);
+ ((struct ufacet*)distrib)->id = 0xDECAFBAD;
+ ufacet_is_init = 1;
+ return RES_OK;
+}
+
+static void
+ufacet_release(void* distrib)
+{
+ NCHECK(distrib, NULL);
+ CHECK(((struct ufacet*)distrib)->id, 0xDECAFBAD);
+ ufacet_is_init = 0;
+}
+
+static void
+ufacet_sample
+ (void* distrib,
+ const double u,
+ const double v,
+ const double wo[3],
+ const double N[3],
+ double wh[3],
+ double* pdf)
+{
+ struct ufacet* ufacet = distrib;
+ NCHECK(ufacet, NULL);
+ CHECK(u >= 0 && u < 1, 1);
+ CHECK(v >= 0 && v < 1, 1);
+ NCHECK(wo, NULL);
+ NCHECK(N, NULL);
+ NCHECK(wh, NULL);
+ NCHECK(pdf, NULL);
+ CHECK(ufacet->u, u);
+ CHECK(ufacet->v, v);
+ CHECK(d3_eq(ufacet->wo, wo), 1);
+ CHECK(d3_eq(ufacet->N, N), 1);
+ d3_normalize(wh, d3(wh, 1.0, 2.0, 3.0));
+ *pdf = ufacet->pdf;
+}
+
+static double
+ufacet_eval
+ (void* distrib,
+ const double wo[3],
+ const double N[3],
+ const double wh[3])
+{
+ struct ufacet* ufacet = distrib;
+ NCHECK(distrib, NULL);
+ NCHECK(wo, NULL);
+ NCHECK(N, NULL);
+ NCHECK(wh, NULL);
+ CHECK(d3_eq(ufacet->wo, wo), 1);
+ CHECK(d3_eq(ufacet->wh, wh), 1);
+ CHECK(d3_eq(ufacet->N, N), 1);
+ return ufacet->value;
+}
+
+static double
+ufacet_pdf
+ (void* distrib,
+ const double wo[3],
+ const double N[3],
+ const double wh[3])
+{
+ struct ufacet* ufacet = distrib;
+ NCHECK(wo, NULL);
+ NCHECK(N, NULL);
+ NCHECK(wh, NULL);
+ CHECK(d3_eq(ufacet->wo, wo), 1);
+ CHECK(d3_eq(ufacet->wh, wh), 1);
+ CHECK(d3_eq(ufacet->N, N), 1);
+ return ufacet->pdf;
+}
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct ufacet* data;
+ struct ssf_microfacet_distribution_type type =
+ SSF_MICROFACET_DISTRIBUTION_TYPE_NULL;
+ struct ssf_microfacet_distribution* distrib;
+ double wo[3], N[3], wh[3], pdf;
+ (void)argc, (void)argv;
+
+ mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+
+ type.init = ufacet_init;
+ type.release = ufacet_release;
+ type.sample = ufacet_sample;
+ type.eval = ufacet_eval;
+ type.pdf = ufacet_pdf;
+ type.sizeof_distribution = sizeof(struct ufacet);
+ type.alignof_distribution = ALIGNOF(struct ufacet);
+
+ #define CREATE ssf_microfacet_distribution_create
+ CHECK(CREATE(NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(CREATE(&allocator, NULL, NULL), RES_BAD_ARG);
+ CHECK(CREATE(NULL, &type, NULL), RES_BAD_ARG);
+ CHECK(CREATE(&allocator, &type, NULL), RES_BAD_ARG);
+ CHECK(CREATE(NULL, NULL, &distrib), RES_BAD_ARG);
+ CHECK(CREATE(&allocator, NULL, &distrib), RES_BAD_ARG);
+
+ CHECK(ufacet_is_init, 0);
+ CHECK(CREATE(NULL, &type, &distrib), RES_OK);
+ CHECK(ufacet_is_init, 1);
+
+ CHECK(ssf_microfacet_distribution_ref_get(NULL), RES_BAD_ARG);
+ CHECK(ssf_microfacet_distribution_ref_get(distrib), RES_OK);
+ CHECK(ssf_microfacet_distribution_ref_put(NULL), RES_BAD_ARG);
+ CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
+ CHECK(ufacet_is_init, 1);
+ CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
+ CHECK(ufacet_is_init, 0);
+
+ CHECK(CREATE(&allocator, &type, &distrib), RES_OK);
+ CHECK(ufacet_is_init, 1);
+ CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
+ CHECK(ufacet_is_init, 0);
+
+ type.init = NULL;
+ CHECK(CREATE(&allocator, &type, &distrib), RES_BAD_ARG);
+ type.init = ufacet_init;
+ type.release = NULL;
+ CHECK(CREATE(&allocator, &type, &distrib), RES_BAD_ARG);
+ type.release = ufacet_release;
+ type.sample = NULL;
+ CHECK(CREATE(&allocator, &type, &distrib), RES_BAD_ARG);
+ type.sample = ufacet_sample;
+ type.eval = NULL;
+ CHECK(CREATE(&allocator, &type, &distrib), RES_BAD_ARG);
+ type.eval = ufacet_eval;
+ type.pdf = NULL;
+ CHECK(CREATE(&allocator, &type, &distrib), RES_BAD_ARG);
+ type.pdf = ufacet_pdf;
+ type.alignof_distribution = 0;
+ CHECK(CREATE(&allocator, &type, &distrib), RES_BAD_ARG);
+ type.alignof_distribution = ALIGNOF(struct ufacet);
+ CHECK(CREATE(&allocator, &type, &distrib), RES_OK);
+ CHECK(ufacet_is_init, 1);
+ #undef CREATE
+
+ CHECK(ssf_microfacet_distribution_get_data(NULL, NULL), RES_BAD_ARG);
+ CHECK(ssf_microfacet_distribution_get_data(distrib, NULL), RES_BAD_ARG);
+ CHECK(ssf_microfacet_distribution_get_data(NULL, (void**)&data), RES_BAD_ARG);
+ CHECK(ssf_microfacet_distribution_get_data(distrib, (void**)&data), RES_OK);
+ CHECK(data->id, 0xDECAFBAD);
+
+ d3_normalize(wo, d3(wo, -1, -1, 0));
+ d3(N, 0.0, 1.0, 0.0);
+ d3_set(data->wo, wo);
+ d3_set(data->N, N);
+ d3_normalize(data->wh, d3(data->wh, 1, 2, 3));
+ data->u = data->v = 0.0;
+ data->pdf = 0.1234;
+ data->value = 0.43;
+
+ ssf_microfacet_distribution_sample(distrib, 0, 0, wo, N, wh, &pdf);
+ CHECK(d3_eq(wh, data->wh), 1);
+ CHECK(pdf, data->pdf);
+ data->u = data->v = 0.5;
+ ssf_microfacet_distribution_sample(distrib, 0.5, 0.5, wo, N, wh, &pdf);
+ CHECK(d3_eq(wh, data->wh), 1);
+ CHECK(pdf, data->pdf);
+
+ CHECK(ssf_microfacet_distribution_eval(distrib, wo, N, wh), data->value);
+ CHECK(ssf_microfacet_distribution_pdf(distrib, wo, N, wh), data->pdf);
+
+ CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
+ CHECK(ufacet_is_init, 0);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}