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:
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;
+}
+