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 5f422f862ad802eb9f0495b0a64ddb291a3852d9
parent 684db093a056512c9f6bdb1e8b4f9c6adcd06b91
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu,  8 Sep 2016 15:39:58 +0200

Test the Fresnel API

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssf.h | 33+++++++++++++++++++++++++++++++--
Msrc/ssf_fresnel.c | 10+++++++++-
Msrc/test_ssf_bxdf.c | 1+
Asrc/test_ssf_fresnel.c | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 192 insertions(+), 3 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -89,6 +89,7 @@ if(NOT NO_TEST) new_test(test_ssf_bsdf) new_test(test_ssf_bxdf) + new_test(test_ssf_fresnel) new_test(test_ssf_specular_reflection) endif() diff --git a/src/ssf.h b/src/ssf.h @@ -80,6 +80,13 @@ BEGIN_DECLS /* Reflects the incoming direction with respect to the surface normal */ SSF_API const struct ssf_bxdf_type ssf_specular_reflection; +/* Fresnel term for perfect reflection */ +SSF_API const struct ssf_fresnel_type ssf_fresnel_no_op; +/* Fresnel term of a dielectric surface */ +SSF_API const struct ssf_fresnel_type ssf_fresnel_dielectric; +/* Fresnel term of a metalic surface */ +SSF_API const struct ssf_fresnel_type ssf_fresnel_conductor; + /******************************************************************************* * BSDF API - Bidirectionnal Scattering Distribution Function. Describes the * way the light is scattered by a surface with a combination of BxDFs. @@ -139,6 +146,28 @@ ssf_fresnel_eval const double cos_theta, /* Cos between facet normal and outgoing dir */ double* value); +/* Retrieve the internal data of the Fresnel term. Usefull for user defined + * Fresnel terms on which the caller has to retrieve their data to setup the + * parameters of their Fresnel equation. */ +SSF_API res_T +ssf_fresnel_get_data + (struct ssf_fresnel* fresnel, + void** data); + +SSF_API res_T +ssf_fresnel_dielectric_setup + (struct ssf_fresnel* fresnel, + /* Refraction id of the medium the incoming ray travels in */ + const double lambda_i, + /* Refraction id of the medium the outgoing transmission ray travels in */ + const double lambda_t); + +SSF_API res_T +ssf_fresnel_conductor_setup + (struct ssf_fresnel* fresnel, + const double eta, /* Real part of the refraction id */ + const double k); /* Imaginary part of the refraction id */ + /******************************************************************************* * BxDF API - Bidirecitonal <Reflectance|Transmittance> distribution function. * Describes how the light is reflected|transmitted by a surface. @@ -167,8 +196,8 @@ ssf_bxdf_sample double dir[4], /* Sampled direction. The PDF is stored in dir[3] */ double* radiance); /* Sampled radiance */ -/* Retrieve the internal data of the BxDF. Usefull for user defined BxDF on - * which the caller has to retrieve them to setup the its parameters */ +/* Retrieve the internal data of the BxDF. Usefull for user defined BxDFs on + * which the caller has to retrieve their data to setup the their parameters */ SSF_API res_T ssf_bxdf_get_data (struct ssf_bxdf* bxdf, diff --git a/src/ssf_fresnel.c b/src/ssf_fresnel.c @@ -114,8 +114,16 @@ res_T ssf_fresnel_eval (struct ssf_fresnel* fresnel, const double cos_theta, double* val) { - if(!fresnel || cos_theta < 0.0) return RES_BAD_ARG; + if(!fresnel || cos_theta < 0.0 || !val) return RES_BAD_ARG; *val = fresnel->type.eval(fresnel->data, cos_theta); return RES_OK; } +res_T +ssf_fresnel_get_data(struct ssf_fresnel* fresnel, void** data) +{ + if(!fresnel || !data) return RES_BAD_ARG; + *data = fresnel->data; + return RES_OK; +} + diff --git a/src/test_ssf_bxdf.c b/src/test_ssf_bxdf.c @@ -59,6 +59,7 @@ bxdf_sample double dir[4]) { struct bxdf* BxDF = bxdf; + NCHECK(BxDF, NULL); CHECK(BxDF->u, u); CHECK(BxDF->v, v); CHECK(d3_eq(BxDF->w, w), 1); diff --git a/src/test_ssf_fresnel.c b/src/test_ssf_fresnel.c @@ -0,0 +1,150 @@ +/* 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" + +static int fresnel_is_init = 0; + +struct ALIGN(64) fresnel { + uint32_t id; + double cos_theta; + double value; +}; + +static res_T +fresnel_init(struct mem_allocator* allocator, void* fresnel) +{ + NCHECK(allocator, NULL); + NCHECK(fresnel, NULL); + CHECK(IS_ALIGNED(fresnel, 64), 1); + ((struct fresnel*)fresnel)->id = 0xDECAFBAD; + fresnel_is_init = 1; + return RES_OK; +} + +static void +fresnel_release(void* fresnel) +{ + NCHECK(fresnel, NULL); + CHECK(((struct fresnel*)fresnel)->id, 0xDECAFBAD); + fresnel_is_init = 0; +} + +static double +fresnel_eval(void* fresnel, const double cos_theta) +{ + struct fresnel* f = fresnel; + NCHECK(f, NULL); + CHECK(f->id, 0xDECAFBAD); + CHECK(f->cos_theta, cos_theta); + return f->value; +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct fresnel* data; + struct ssf_fresnel* fresnel; + struct ssf_fresnel_type type; + double val; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + type.init = fresnel_init; + type.release = fresnel_release; + type.eval = fresnel_eval; + type.sizeof_fresnel = sizeof(struct fresnel); + type.alignof_fresnel = ALIGNOF(struct fresnel); + + CHECK(ssf_fresnel_create(NULL, NULL, NULL), RES_BAD_ARG); + + CHECK(ssf_fresnel_create(NULL, NULL, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_create(&allocator, NULL, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_create(NULL, &type, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_create(&allocator, &type, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_create(NULL, NULL, &fresnel), RES_BAD_ARG); + CHECK(ssf_fresnel_create(&allocator, NULL, &fresnel), RES_BAD_ARG); + + CHECK(fresnel_is_init, 0); + CHECK(ssf_fresnel_create(NULL, &type, &fresnel), RES_OK); + CHECK(fresnel_is_init, 1); + + CHECK(ssf_fresnel_ref_get(NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_ref_get(fresnel), RES_OK); + CHECK(ssf_fresnel_ref_put(NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_ref_put(fresnel), RES_OK); + CHECK(fresnel_is_init, 1); + CHECK(ssf_fresnel_ref_put(fresnel), RES_OK); + CHECK(fresnel_is_init, 0); + + CHECK(ssf_fresnel_create(&allocator, &type, &fresnel), RES_OK); + CHECK(fresnel_is_init, 1); + CHECK(ssf_fresnel_ref_put(fresnel), RES_OK); + CHECK(fresnel_is_init, 0); + + type.init = NULL; + CHECK(ssf_fresnel_create(&allocator, &type, &fresnel), RES_BAD_ARG); + CHECK(fresnel_is_init, 0); + type.init = fresnel_init; + type.release = NULL; + CHECK(ssf_fresnel_create(&allocator, &type, &fresnel), RES_BAD_ARG); + CHECK(fresnel_is_init, 0); + type.release = fresnel_release; + type.eval = NULL; + CHECK(ssf_fresnel_create(&allocator, &type, &fresnel), RES_BAD_ARG); + CHECK(fresnel_is_init, 0); + type.eval = fresnel_eval; + type.alignof_fresnel = 0; + CHECK(ssf_fresnel_create(&allocator, &type, &fresnel), RES_BAD_ARG); + CHECK(fresnel_is_init, 0); + type.alignof_fresnel = ALIGNOF(struct fresnel); + CHECK(ssf_fresnel_create(&allocator, &type, &fresnel), RES_OK); + CHECK(fresnel_is_init, 1); + + CHECK(ssf_fresnel_get_data(NULL, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_get_data(fresnel, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_get_data(NULL, (void**)&data), RES_BAD_ARG); + CHECK(ssf_fresnel_get_data(fresnel, (void**)&data), RES_OK); + + CHECK(data->id, 0xDECAFBAD); + data->cos_theta = 0.1; + data->value = 1.234; + + CHECK(ssf_fresnel_eval(NULL, -1, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(fresnel, -1, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(NULL, 0.1, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(fresnel, 0.1, NULL), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(NULL, -1, &val), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(fresnel, -1, &val), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(NULL, 0.1, &val), RES_BAD_ARG); + CHECK(ssf_fresnel_eval(fresnel, 0.1, &val), RES_OK); + CHECK(val, data->value); + data->value = 8.1; + CHECK(ssf_fresnel_eval(fresnel, 0.1, &val), RES_OK); + CHECK(val, data->value); + + CHECK(fresnel_is_init, 1); + CHECK(ssf_fresnel_ref_put(fresnel), RES_OK); + CHECK(fresnel_is_init, 0); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} +