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 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:
Mcmake/CMakeLists.txt | 1+
Asrc/test_ssf_microfacet_distribution.c | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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; +}