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 f17c6dc147e7b17ff3b87b6b621c1e6758281e46
parent 8b9e155d5bf70b9b0cb2ee37675d840100816dda
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon,  4 Sep 2017 11:11:17 +0200

Remove the BxDF abstraction

A BSDF is no more a composition of BxDFs. The builtin BxDFs are
transformed in BSDFs and the ssf_specular_transmission BTDF is removed
since it is no more used in a composition.

Diffstat:
Mcmake/CMakeLists.txt | 6+-----
Msrc/ssf.h | 145+++++++++++++++++++++----------------------------------------------------------
Msrc/ssf_bsdf.c | 160+++++++++++++++++++++++++------------------------------------------------------
Msrc/ssf_bsdf_c.h | 21+++++++++++++++++++++
Dsrc/ssf_bxdf.c | 162-------------------------------------------------------------------------------
Dsrc/ssf_bxdf_c.h | 43-------------------------------------------
Msrc/ssf_lambertian_reflection.c | 22+++++++++++-----------
Msrc/ssf_microfacet_reflection.c | 68++++++++++++++++++++++++++++++++++----------------------------------
Msrc/ssf_specular_dielectric_dielectric_interface.c | 42+++++++++++++++++++++---------------------
Msrc/ssf_specular_reflection.c | 26+++++++++++++-------------
Dsrc/ssf_specular_transmission.c | 122-------------------------------------------------------------------------------
Msrc/ssf_thin_specular_dielectric.c | 47+++++++++++++++++++++++------------------------
Msrc/test_ssf_bsdf.c | 241+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Dsrc/test_ssf_bxdf.c | 218-------------------------------------------------------------------------------
Msrc/test_ssf_lambertian_reflection.c | 24++++++++++++------------
Msrc/test_ssf_microfacet_reflection.c | 22+++++++++++-----------
Msrc/test_ssf_specular_reflection.c | 28++++++++++++++--------------
Msrc/test_ssf_thin_specular_dielectric.c | 30+++++++++++++++---------------
Msrc/test_ssf_utils.h | 40++++++++++++++++++++--------------------
19 files changed, 454 insertions(+), 1013 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -46,7 +46,7 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SSF_FILES_DOC COPYING README.md) set(SSF_FILES_INC_API ssf.h) set(SSF_FILES_INC - ssf_bxdf_c.h + ssf_bsdf_c.h ssf_fresnel_c.h ssf_microfacet_distribution_c.h ssf_optics.h) @@ -54,7 +54,6 @@ set(SSF_FILES_SRC ssf_beckmann_distribution.c ssf_blinn_distribution.c ssf_bsdf.c - ssf_bxdf.c ssf_fresnel.c ssf_fresnel_constant.c ssf_fresnel_dielectric_conductor.c @@ -65,7 +64,6 @@ set(SSF_FILES_SRC ssf_microfacet_reflection.c ssf_specular_dielectric_dielectric_interface.c ssf_specular_reflection.c - ssf_specular_transmission.c ssf_thin_specular_dielectric.c) rcmake_prepend_path(SSF_FILES_SRC ${SSF_SOURCE_DIR}) rcmake_prepend_path(SSF_FILES_INC ${SSF_SOURCE_DIR}) @@ -104,7 +102,6 @@ if(NOT NO_TEST) new_test(test_ssf_beckmann_distribution) new_test(test_ssf_blinn_distribution) new_test(test_ssf_bsdf) - new_test(test_ssf_bxdf) new_test(test_ssf_fresnel) new_test(test_ssf_fresnel_constant) new_test(test_ssf_fresnel_dielectric_conductor) @@ -114,7 +111,6 @@ if(NOT NO_TEST) new_test(test_ssf_microfacet_distribution) new_test(test_ssf_microfacet_reflection) new_test(test_ssf_specular_reflection) - new_test(test_ssf_specular_transmission) new_test(test_ssf_thin_specular_dielectric) rcmake_copy_runtime_libraries(test_ssf_beckmann_distribution) diff --git a/src/ssf.h b/src/ssf.h @@ -44,8 +44,6 @@ struct ssp_rng; /* Opaque data types */ struct ssf_bsdf; /* Bidirectional Scattering Distribution Function */ -struct ssf_bsdf_view; /* Current state of the BSDF */ -struct ssf_bxdf; /* Bidirectional <Reflec|Transmit>tance Distribution Function */ struct ssf_fresnel; /* Equation of the Fresnel term */ struct ssf_microfacet_distribution; @@ -57,20 +55,20 @@ enum ssf_bxdf_flag { SSF_GLOSSY = BIT(4) }; -/* Generic BxDF type descriptor. Note that by convention the outgoing direction +/* Generic BSDF type descriptor. Note that by convention the outgoing direction * `wo' and the incoming direction `wi' point outward the surface. Furthermore, * `wo' and the normal N must point on the same side of the surface. As a * consequence the reflected or refracted direction `wi' must point on the same * side or on the opposite side of `N', respectively. */ -struct ssf_bxdf_type { - res_T (*init)(struct mem_allocator* allocator, void* bxdf); - void (*release)(void* bxdf); +struct ssf_bsdf_type { + res_T (*init)(struct mem_allocator* allocator, void* bsdf); + void (*release)(void* bsdf); - /* Sample a direction `wi' wrt `wo' whose pdf is BxDF(wo, wi) |wi.n|. Return - * the value of BxDF(wo, wi) */ + /* Sample a direction `wi' wrt `wo' whose pdf is BSDF(wo, wi) |wi.n|. Return + * the value of BSDF(wo, wi) */ double (*sample) - (void* bxdf, + (void* bsdf, struct ssp_rng* rng, /* Random number generator */ const double wo[3], /* Normalized outgoing direction */ const double N[3], /* Normalized surface normal */ @@ -81,7 +79,7 @@ struct ssf_bxdf_type { /* Evaluate the BxDF wrt to wo and wi */ double (*eval) - (void* bxdf, + (void* bsdf, const double wo[3], /* Normalized outgoing direction */ const double N[3], /* Normalized surface normal */ const double wi[3]);/* Normalized incoming direction */ @@ -89,16 +87,16 @@ struct ssf_bxdf_type { /* Probability density function */ double (*pdf) - (void* bxdf, + (void* bsdf, const double wo[3], /* Normalized outgoing direction */ const double N[3], /* Normalized surface normal */ const double wi[3]);/* Normalized incoming direction */ - size_t sizeof_bxdf; /* In Bytes */ - size_t alignof_bxdf; /* In Bytes */ + size_t sizeof_bsdf; /* In Bytes */ + size_t alignof_bsdf; /* In Bytes */ }; -#define SSF_BXDF_TYPE_NULL__ {NULL, NULL, NULL, NULL, NULL, 0, 1} -static const struct ssf_bxdf_type SSF_BXDF_TYPE_NULL = SSF_BXDF_TYPE_NULL__; +#define SSF_BSDF_TYPE_NULL__ {NULL, NULL, NULL, NULL, NULL, 0, 1} +static const struct ssf_bsdf_type SSF_BXDF_TYPE_NULL = SSF_BSDF_TYPE_NULL__; /* Generic Fresnel term descriptor */ struct ssf_fresnel_type { @@ -156,7 +154,7 @@ SSF_MICROFACET_DISTRIBUTION_TYPE_NULL = SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__; BEGIN_DECLS /******************************************************************************* - * Built-in BxDFs + * Built-in BSDFs ******************************************************************************/ /* Dirac distribution whose incoming direction `wi' is the reflection of the * supplied direction `wo' with respect to the surface normal `N'. The @@ -165,11 +163,11 @@ BEGIN_DECLS * Since it is a dirac distribution, the returned value of the `eval' and `pdf' * function is always 0 while the pdf returned by `sample' function is * infinity. */ -SSF_API const struct ssf_bxdf_type ssf_specular_reflection; +SSF_API const struct ssf_bsdf_type ssf_specular_reflection; /* Reflects the same intensity in all direction independently of the incoming * direction; fr(wo, wr) = R/PI */ -SSF_API const struct ssf_bxdf_type ssf_lambertian_reflection; +SSF_API const struct ssf_bsdf_type ssf_lambertian_reflection; /* Glossy reflections with respect to a microfacet distribution. It is based on * the Torrance Sparrow BRDF to provide a general Microfacet-based BRDF model @@ -182,7 +180,7 @@ SSF_API const struct ssf_bxdf_type ssf_lambertian_reflection; * scattering of lights into the microfacet structure and remove them with the * 'G' term. As a consequence, this model does not satisfy the energy * conservation property */ -SSF_API const struct ssf_bxdf_type ssf_microfacet_reflection; +SSF_API const struct ssf_bsdf_type ssf_microfacet_reflection; /* Glossy reflections with respect to a microfacet distribution. In contrast to * the ssp_microfacet_reflection model, this BRDF ensures, by design, the @@ -191,7 +189,7 @@ SSF_API const struct ssf_bxdf_type ssf_microfacet_reflection; * functions return invalid value. However, it is well suited for Monte Carlo * integrations that only need to sample a direction and to define its * associated directional reflectance */ -SSF_API const struct ssf_bxdf_type ssf_microfacet2_reflection; +SSF_API const struct ssf_bsdf_type ssf_microfacet2_reflection; /* This BSDF consists in a model of refraction effects within a thin slab of a * dielectric material, combine with a dirac distribution of the reflection at @@ -206,18 +204,16 @@ SSF_API const struct ssf_bxdf_type ssf_microfacet2_reflection; * are not ideal dielectrics, the slab is also supposed to absorb incoming * radiation. The absorption coefficient "alpha" of the material is provided * by the user. */ -SSF_API const struct ssf_bxdf_type ssf_thin_specular_dielectric; - - -SSF_API const struct ssf_bxdf_type ssf_specular_dielectric_dielectric_interface; +SSF_API const struct ssf_bsdf_type ssf_thin_specular_dielectric; -/* Dirac distribution whose incoming direction `wi' is refracted wrt N and a - * dielectric/dielectric fresnel term `Fr'. - * fr(wo, wi) = (1 - Fr(|wi.N|)) * delta(wo - Refract(wi, N)) / |wi.N| +/* Dirac distribution whose incoming direction `wi' is either refracted or + * reflecter wrt N and a dielectric/dielectric fresnel term `Fr'. + * f_reflected(wo, wi) = Fr(|wi.N|) * delta(wo - Reflect(wi, N)) / |wi.N| + * f_refracted(wo, wi) = (1-Fr(|wi.N|)) * delta(wo - Refract(wi, N)) / |wi.N| * Since it is a dirac distribution, the returned value of the `eval' and `pdf' * function is always 0 while the pdf returned by `sample' function is * infinity. */ -SSF_API const struct ssf_bxdf_type ssf_specular_transmission; +SSF_API const struct ssf_bsdf_type ssf_specular_dielectric_dielectric_interface; /******************************************************************************* * Built-in Fresnel terms @@ -263,17 +259,17 @@ SSF_API const struct ssf_microfacet_distribution_type ssf_beckmann_distribution; SSF_API const struct ssf_microfacet_distribution_type ssf_blinn_distribution; /******************************************************************************* - * BSDF API - Bidirectional Scattering Distribution Function. Describes the - * way the light is scattered by a surface with a combination of BxDFs. Note - * that by convention the outgoing direction `wo' and the incoming direction - * `wi' point outward the surface. Furthermore, `wo' and the normal `N' must - * point on the same side of the surface. As a consequence the reflected or - * refracted direction `wi' must point on the same side or on the opposite side - * of `N', respectively. + * BSDF API - Bidirectional Scattering Distribution Function. Describes the way + * the light is scattered by a surface. Note that by convention the outgoing + * direction `wo' and the incoming direction `wi' point outward the surface. + * Furthermore, `wo' and the normal `N' must point on the same side of the + * surface. As a consequence the reflected or refracted direction `wi' must + * point on the same side or on the opposite side of `N', respectively. ******************************************************************************/ SSF_API res_T ssf_bsdf_create (struct mem_allocator* allocator, /* May be NULL <=> Use default allocator */ + const struct ssf_bsdf_type* type, struct ssf_bsdf** bsdf); SSF_API res_T @@ -284,16 +280,6 @@ SSF_API res_T ssf_bsdf_ref_put (struct ssf_bsdf* bsdf); -SSF_API res_T -ssf_bsdf_add - (struct ssf_bsdf* bsdf, - struct ssf_bxdf* bxdf, - const double weight); - -SSF_API res_T -ssf_bsdf_clear - (struct ssf_bsdf* bsdf); - /* Sample a direction `wi' wrt `wo' whose pdf is BSDF(wo, wi) |wi.n|. Return * the directionnal reflectance, i.e. pdf to be reflected in *any* direction * wrt to the incident direction `wi' */ @@ -321,79 +307,30 @@ ssf_bsdf_pdf const double N[3], /* Normalized surface normal */ const double wi[3]); /* Normalized outgoing direction */ -/******************************************************************************* - * BxDF API - Bidirectional <Reflectance|Transmittance> distribution function. - * Describes how the light is reflected|transmitted by a surface. Note that by - * convention the outgoing direction `wo' and the incoming direction `wi' point - * outward the surface. - ******************************************************************************/ SSF_API res_T -ssf_bxdf_create - (struct mem_allocator* allocator, - const struct ssf_bxdf_type* type, - struct ssf_bxdf** bxdf); - -SSF_API res_T -ssf_bxdf_ref_get - (struct ssf_bxdf* bxdf); - -SSF_API res_T -ssf_bxdf_ref_put - (struct ssf_bxdf* bxdf); - -/* Sample a direction `wi' wrt `wo' whose pdf is BxDF(wo, wi) |wi.n|. Return - * the directionnal reflectance, i.e. pdf to be reflected in *any* direction - * wrt to the incident direction `wi' */ -SSF_API double -ssf_bxdf_sample - (struct ssf_bxdf* bxdf, - struct ssp_rng* rng, /* Random number generator */ - const double wo[3], /* Normalized outgoing direction */ - const double N[3], /* Normalized surface normal */ - double wi[3], /* Sampled normalized incoming direction. */ - int* type, /* Sampled BxDF type. Combination of ssf_bxdf_flag */ - double* pdf); /* PDF of the sampled direction */ - -SSF_API double -ssf_bxdf_eval - (struct ssf_bxdf* bxdf, - const double wo[3], /* Normalized outgoing direction */ - const double N[3], /* Normalized surface normal */ - const double wi[3]);/* Normalized incoming direction */ - -SSF_API double /* Probability density function */ -ssf_bxdf_pdf - (struct ssf_bxdf* bxdf, - const double wo[3], /* Normalized outgoing direction */ - const double N[3], /* Normalized surface normal */ - const double wi[3]);/* Normalized incoming dir. Point outward the surface */ - -/* Retrieve the internal data of the BxDF. Usefull for user defined BxDFs on - * which the caller has to retrieve their data to setup their parameters */ -SSF_API res_T -ssf_bxdf_get_data - (struct ssf_bxdf* bxdf, +ssf_bsdf_get_data + (struct ssf_bsdf* bsdf, void** data); SSF_API res_T ssf_specular_reflection_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, struct ssf_fresnel* fresnel); SSF_API res_T ssf_lambertian_reflection_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, const double reflectivity); SSF_API res_T ssf_microfacet_reflection_setup - (struct ssf_bxdf* data, + (struct ssf_bsdf* bsdf, struct ssf_fresnel* fresnel, struct ssf_microfacet_distribution* distrib); SSF_API res_T ssf_thin_specular_dielectric_setup - (struct ssf_bxdf* data, + (struct ssf_bsdf* bsdf, const double absorption, /* In [0, 1] */ const double eta_i, /* Refraction id of the medium the ray travels in */ const double eta_t, /* Refraction id of the thin dielectric slab */ @@ -401,16 +338,10 @@ ssf_thin_specular_dielectric_setup SSF_API res_T ssf_specular_dielectric_dielectric_interface_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, const double eta_i, const double eta_t); -SSF_API res_T -ssf_specular_transmission_setup - (struct ssf_bxdf* data, - const double eta_i, /* Refraction id of the medium the ray travels in */ - const double eta_t); /* Refraction id of the opposite medium */ - /******************************************************************************* * Fresnel API - Define the equation of the fresnel term ******************************************************************************/ diff --git a/src/ssf_bsdf.c b/src/ssf_bsdf.c @@ -13,46 +13,28 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#define _POSIX_C_SOURCE 200112L /* nextafter */ - #include "ssf.h" -#include "ssf_bxdf_c.h" +#include "ssf_bsdf_c.h" #include <rsys/double3.h> -#include <rsys/double4.h> #include <rsys/mem_allocator.h> #include <rsys/ref_count.h> -#include <star/ssp.h> - -#define MAX_BxDFs 8 - -struct ssf_bsdf { - struct ssf_bxdf* bxdfs[MAX_BxDFs]; - - double uweights[MAX_BxDFs]; /* Unormalized component weights */ - double weights[MAX_BxDFs]; /* Normalized weights */ - int outdated_weights; /* Define if the normalized weights are outdated */ - - size_t nbxdfs; - - ref_T ref; - struct mem_allocator* allocator; -}; +#include <string.h> /******************************************************************************* * Helper functions ******************************************************************************/ -static INLINE void -bsdf_normalize_weights(struct ssf_bsdf* bsdf) +static INLINE int +check_bsdf_type(const struct ssf_bsdf_type* type) { - double weights_sum = 0; - size_t i; - ASSERT(bsdf); - if(!bsdf->outdated_weights) return; - FOR_EACH(i, 0, bsdf->nbxdfs) weights_sum += bsdf->uweights[i]; - FOR_EACH(i, 0, bsdf->nbxdfs) bsdf->weights[i] = bsdf->uweights[i]/weights_sum; - bsdf->outdated_weights = 0; + return type + && type->init + && type->release + && type->sample + && type->eval + && type->pdf + && IS_POW2(type->alignof_bsdf); } static void @@ -60,7 +42,10 @@ bsdf_release(ref_T* ref) { struct ssf_bsdf* bsdf = CONTAINER_OF(ref, struct ssf_bsdf, ref); ASSERT(ref); - SSF(bsdf_clear(bsdf)); + if(bsdf->data) { + bsdf->type.release(bsdf->data); + MEM_RM(bsdf->allocator, bsdf->data); + } MEM_RM(bsdf->allocator, bsdf); } @@ -68,25 +53,38 @@ bsdf_release(ref_T* ref) * Exported functions ******************************************************************************/ res_T -ssf_bsdf_create(struct mem_allocator* allocator, struct ssf_bsdf** out_bsdf) +ssf_bsdf_create + (struct mem_allocator* allocator, + const struct ssf_bsdf_type* type, + struct ssf_bsdf** out_bsdf) { struct mem_allocator* mem_allocator = NULL; struct ssf_bsdf* bsdf = NULL; res_T res = RES_OK; - if(!out_bsdf) { + if(!out_bsdf || !check_bsdf_type(type)) { res = RES_BAD_ARG; goto error; } - mem_allocator = allocator ? allocator : &mem_default_allocator; bsdf = MEM_CALLOC(mem_allocator, 1, sizeof(struct ssf_bsdf)); if(!bsdf) { res = RES_MEM_ERR; goto error; } - bsdf->allocator = mem_allocator; ref_init(&bsdf->ref); + bsdf->allocator = mem_allocator; + bsdf->type = *type; + + bsdf->data = MEM_ALLOC_ALIGNED + (bsdf->allocator, bsdf->type.sizeof_bsdf, bsdf->type.alignof_bsdf); + if(!bsdf->data) { + res = RES_MEM_ERR; + goto error; + } + memset(bsdf->data, 0, bsdf->type.sizeof_bsdf); + res = bsdf->type.init(mem_allocator, bsdf->data); + if(res != RES_OK) goto error; exit: if(out_bsdf) *out_bsdf = bsdf; @@ -115,32 +113,6 @@ ssf_bsdf_ref_put(struct ssf_bsdf* bsdf) return RES_OK; } -res_T -ssf_bsdf_add(struct ssf_bsdf* bsdf, struct ssf_bxdf* bxdf, const double weight) -{ - if(!bsdf || !bxdf || weight < 0) return RES_BAD_ARG; - if(bsdf->nbxdfs >= MAX_BxDFs) return RES_MEM_ERR; - if(weight == 0) return RES_OK; - SSF(bxdf_ref_get(bxdf)); - bsdf->bxdfs[bsdf->nbxdfs] = bxdf; - bsdf->uweights[bsdf->nbxdfs] = weight; - bsdf->outdated_weights = 1; - ++bsdf->nbxdfs; - return RES_OK; -} - -res_T -ssf_bsdf_clear(struct ssf_bsdf* bsdf) -{ - size_t i; - if(!bsdf) return RES_BAD_ARG; - FOR_EACH(i, 0, bsdf->nbxdfs) { - SSF(bxdf_ref_put(bsdf->bxdfs[i])); - } - bsdf->nbxdfs = 0; - return RES_OK; -} - double ssf_bsdf_sample (struct ssf_bsdf* bsdf, @@ -149,72 +121,42 @@ ssf_bsdf_sample const double N[3], double wi[3], int* type, - double* out_pdf) + double* pdf) { - double cumul; - double R; - double r; - double pdf; - size_t i; - ASSERT(bsdf && rng && wi && N && wo && type && out_pdf); + ASSERT(bsdf && rng && wo && N && wi && type && pdf); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); - - if(!bsdf->nbxdfs) { - *out_pdf = 0; - *type = 0; - return 0; - } - if(bsdf->nbxdfs == 1) { - return ssf_bxdf_sample(bsdf->bxdfs[0], rng, wo, N, wi, type, out_pdf); - } - - bsdf_normalize_weights(bsdf); - - /* Sample a component */ - r = ssp_rng_canonical(rng); - cumul = bsdf->weights[0]; - FOR_EACH(i, 0, bsdf->nbxdfs-1) { - if(r <= cumul) break; - cumul += bsdf->weights[i]; - } - - /* Sample a direction from the selected component */ - R = ssf_bxdf_sample(bsdf->bxdfs[i], rng, wo, N, wi, type, &pdf); - *out_pdf = pdf*bsdf->weights[i]; - return R; + return bsdf->type.sample(bsdf->data, rng, wo, N, wi, type, pdf); } double -ssf_bsdf_pdf +ssf_bsdf_eval (struct ssf_bsdf* bsdf, const double wo[3], const double N[3], const double wi[3]) { - double pdf = 0; - size_t i; - ASSERT(bsdf); - bsdf_normalize_weights(bsdf); - FOR_EACH(i, 0, bsdf->nbxdfs) { - pdf += ssf_bxdf_pdf(bsdf->bxdfs[i], wo, N, wi) * bsdf->weights[i]; - } - return pdf; + ASSERT(bsdf && wo && N && wi); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi)); + return bsdf->type.eval(bsdf->data, wo, N, wi); } double -ssf_bsdf_eval +ssf_bsdf_pdf (struct ssf_bsdf* bsdf, const double wo[3], const double N[3], const double wi[3]) { - double fr = 0; - size_t i; - ASSERT(bsdf); - bsdf_normalize_weights(bsdf); - FOR_EACH(i, 0, bsdf->nbxdfs) { - fr += bsdf->weights[i] * ssf_bxdf_eval(bsdf->bxdfs[i], wo, N, wi); - } - return fr; + ASSERT(bsdf && wi && wo); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi)); + return bsdf->type.pdf(bsdf->data, wo, N, wi); +} + +res_T +ssf_bsdf_get_data(struct ssf_bsdf* bsdf, void** data) +{ + if(!bsdf || !data) return RES_BAD_ARG; + *data = bsdf->data; + return RES_OK; } diff --git a/src/ssf_bsdf_c.h b/src/ssf_bsdf_c.h @@ -16,7 +16,28 @@ #ifndef SSF_BSDF_C_H #define SSF_BSDF_C_H +#include "ssf.h" +#include <rsys/ref_count.h> +struct mem_allocator; + +struct ssf_bsdf { + struct ssf_bsdf_type type; + void* data; /* Specific internal data of the BxDF */ + + /* Private data */ + ref_T ref; + struct mem_allocator* allocator; +}; + +#define BSDF_TYPE_EQ(A, B) \ + ( (A)->init == (B)->init \ + && (A)->release == (B)->release \ + && (A)->sample == (B)->sample \ + && (A)->eval == (B)->eval \ + && (A)->pdf == (B)->pdf \ + && (A)->sizeof_bsdf == (B)->sizeof_bsdf \ + && (A)->alignof_bsdf == (B)->alignof_bsdf) #endif /* SSF_BSDF_C_H */ diff --git a/src/ssf_bxdf.c b/src/ssf_bxdf.c @@ -1,162 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2017 (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 "ssf_bxdf_c.h" - -#include <rsys/double3.h> -#include <rsys/mem_allocator.h> -#include <rsys/ref_count.h> - -#include <string.h> - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static INLINE int -check_bxdf_type(const struct ssf_bxdf_type* type) -{ - return type - && type->init - && type->release - && type->sample - && type->eval - && type->pdf - && IS_POW2(type->alignof_bxdf); -} - -static void -bxdf_release(ref_T* ref) -{ - struct ssf_bxdf* bxdf = CONTAINER_OF(ref, struct ssf_bxdf, ref); - ASSERT(ref); - if(bxdf->data) { - bxdf->type.release(bxdf->data); - MEM_RM(bxdf->allocator, bxdf->data); - } - MEM_RM(bxdf->allocator, bxdf); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -ssf_bxdf_create - (struct mem_allocator* allocator, - const struct ssf_bxdf_type* type, - struct ssf_bxdf** out_bxdf) -{ - struct mem_allocator* mem_allocator = NULL; - struct ssf_bxdf* bxdf = NULL; - res_T res = RES_OK; - - if(!out_bxdf || !check_bxdf_type(type)) { - res = RES_BAD_ARG; - goto error; - } - mem_allocator = allocator ? allocator : &mem_default_allocator; - bxdf = MEM_CALLOC(mem_allocator, 1, sizeof(struct ssf_bxdf)); - if(!bxdf) { - res = RES_MEM_ERR; - goto error; - } - ref_init(&bxdf->ref); - bxdf->allocator = mem_allocator; - bxdf->type = *type; - - bxdf->data = MEM_ALLOC_ALIGNED - (bxdf->allocator, bxdf->type.sizeof_bxdf, bxdf->type.alignof_bxdf); - if(!bxdf->data) { - res = RES_MEM_ERR; - goto error; - } - memset(bxdf->data, 0, bxdf->type.sizeof_bxdf); - res = bxdf->type.init(mem_allocator, bxdf->data); - if(res != RES_OK) goto error; - -exit: - if(out_bxdf) *out_bxdf = bxdf; - return res; -error: - if(bxdf) { - SSF(bxdf_ref_put(bxdf)); - bxdf = NULL; - } - goto exit; -} - -res_T -ssf_bxdf_ref_get(struct ssf_bxdf* bxdf) -{ - if(!bxdf) return RES_BAD_ARG; - ref_get(&bxdf->ref); - return RES_OK; -} - -res_T -ssf_bxdf_ref_put(struct ssf_bxdf* bxdf) -{ - if(!bxdf) return RES_BAD_ARG; - ref_put(&bxdf->ref, bxdf_release); - return RES_OK; -} - -double -ssf_bxdf_sample - (struct ssf_bxdf* bxdf, - struct ssp_rng* rng, - const double wo[3], - const double N[3], - double wi[3], - int* type, - double* pdf) -{ - ASSERT(bxdf && rng && wo && N && wi && type && pdf); - ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); - return bxdf->type.sample(bxdf->data, rng, wo, N, wi, type, pdf); -} - -double -ssf_bxdf_eval - (struct ssf_bxdf* bxdf, - const double wo[3], - const double N[3], - const double wi[3]) -{ - ASSERT(bxdf && wo && N && wi); - ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi)); - return bxdf->type.eval(bxdf->data, wo, N, wi); -} - -double -ssf_bxdf_pdf - (struct ssf_bxdf* bxdf, - const double wo[3], - const double N[3], - const double wi[3]) -{ - ASSERT(bxdf && wi && wo); - ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi)); - return bxdf->type.pdf(bxdf->data, wo, N, wi); -} - -res_T -ssf_bxdf_get_data(struct ssf_bxdf* bxdf, void** data) -{ - if(!bxdf || !data) return RES_BAD_ARG; - *data = bxdf->data; - return RES_OK; -} - diff --git a/src/ssf_bxdf_c.h b/src/ssf_bxdf_c.h @@ -1,43 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2017 (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/>. */ - -#ifndef SSF_BXDF_C_H -#define SSF_BXDF_C_H - -#include "ssf.h" -#include <rsys/ref_count.h> - -struct mem_allocator; - -struct ssf_bxdf { - struct ssf_bxdf_type type; - void* data; /* Specific internal data of the BxDF */ - - /* Private data */ - ref_T ref; - struct mem_allocator* allocator; -}; - -#define BXDF_TYPE_EQ(A, B) \ - ( (A)->init == (B)->init \ - && (A)->release == (B)->release \ - && (A)->sample == (B)->sample \ - && (A)->eval == (B)->eval \ - && (A)->pdf == (B)->pdf \ - && (A)->sizeof_bxdf == (B)->sizeof_bxdf \ - && (A)->alignof_bxdf == (B)->alignof_bxdf) - -#endif /* SSF_BXDF_C_H */ - diff --git a/src/ssf_lambertian_reflection.c b/src/ssf_lambertian_reflection.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssf.h" -#include "ssf_bxdf_c.h" +#include "ssf_bsdf_c.h" #include <rsys/double3.h> #include <rsys/double33.h> @@ -29,17 +29,17 @@ struct lambertian_reflection { * Private functions ******************************************************************************/ static res_T -lambertian_reflection_init(struct mem_allocator* allocator, void* bxdf) +lambertian_reflection_init(struct mem_allocator* allocator, void* bsdf) { - ASSERT(bxdf); + ASSERT(bsdf); (void)allocator; - ((struct lambertian_reflection*)bxdf)->reflectivity = 0.0; + ((struct lambertian_reflection*)bsdf)->reflectivity = 0.0; return RES_OK; } static void -lambertian_reflection_release(void* bxdf) -{ (void)bxdf; } +lambertian_reflection_release(void* bsdf) +{ (void)bsdf; } static double lambertian_reflection_eval @@ -90,7 +90,7 @@ lambertian_reflection_pdf /******************************************************************************* * Exorted symbols ******************************************************************************/ -const struct ssf_bxdf_type ssf_lambertian_reflection = { +const struct ssf_bsdf_type ssf_lambertian_reflection = { lambertian_reflection_init, lambertian_reflection_release, lambertian_reflection_sample, @@ -101,11 +101,11 @@ const struct ssf_bxdf_type ssf_lambertian_reflection = { }; res_T -ssf_lambertian_reflection_setup(struct ssf_bxdf* bxdf, const double reflectivity) +ssf_lambertian_reflection_setup(struct ssf_bsdf* bsdf, const double reflectivity) { - if(!bxdf || reflectivity < 0 || reflectivity > 1) return RES_BAD_ARG; - if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_lambertian_reflection)) return RES_BAD_ARG; - ((struct lambertian_reflection*)bxdf->data)->reflectivity = reflectivity; + if(!bsdf || reflectivity < 0 || reflectivity > 1) return RES_BAD_ARG; + if(!BSDF_TYPE_EQ(&bsdf->type, &ssf_lambertian_reflection)) return RES_BAD_ARG; + ((struct lambertian_reflection*)bsdf->data)->reflectivity = reflectivity; return RES_OK; } diff --git a/src/ssf_microfacet_reflection.c b/src/ssf_microfacet_reflection.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssf.h" -#include "ssf_bxdf_c.h" +#include "ssf_bsdf_c.h" #include "ssf_optics.h" #include <rsys/double3.h> @@ -30,34 +30,34 @@ struct microfacet_reflection { static res_T microfacet_reflection_init(struct mem_allocator* allocator, void* data) { - struct microfacet_reflection* bxdf = data; - ASSERT(bxdf); + struct microfacet_reflection* bsdf = data; + ASSERT(bsdf); (void)allocator; - bxdf->fresnel = NULL; - bxdf->distrib = NULL; + bsdf->fresnel = NULL; + bsdf->distrib = NULL; return RES_OK; } static void microfacet_reflection_release(void* data) { - struct microfacet_reflection* bxdf = data; - ASSERT(bxdf); - if(bxdf->fresnel) - SSF(fresnel_ref_put(bxdf->fresnel)); - if(bxdf->distrib) - SSF(microfacet_distribution_ref_put(bxdf->distrib)); + struct microfacet_reflection* bsdf = data; + ASSERT(bsdf); + if(bsdf->fresnel) + SSF(fresnel_ref_put(bsdf->fresnel)); + if(bsdf->distrib) + SSF(microfacet_distribution_ref_put(bsdf->distrib)); } static FINLINE double microfacet_reflection_eval (void* data, const double wo[3], const double N[3], const double wi[3]) { - struct microfacet_reflection* bxdf = data; + struct microfacet_reflection* bsdf = data; double wh[3]; double cos_wo_N, cos_wi_N, cos_wh_N, cos_wh_wo, cos_wh_wi; double F, D, G; - ASSERT(bxdf && bxdf->fresnel && bxdf->distrib); + ASSERT(bsdf && bsdf->fresnel && bsdf->distrib); ASSERT(wo && N && wi); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi)); ASSERT(d3_dot(wo, N) > 0 && d3_dot(wi, N) > 0); @@ -70,8 +70,8 @@ microfacet_reflection_eval cos_wh_wi = d3_dot(wh, wi); cos_wh_wo = cos_wh_wi; - F = ssf_fresnel_eval(bxdf->fresnel, cos_wh_wi); - D = ssf_microfacet_distribution_eval(bxdf->distrib, wo, N, wh); + F = ssf_fresnel_eval(bsdf->fresnel, cos_wh_wi); + D = ssf_microfacet_distribution_eval(bsdf->distrib, wo, N, wh); /* Cook Torrance geometry term */ G = MMIN((2*cos_wh_N*cos_wo_N)/cos_wh_wo, (2*cos_wh_N*cos_wi_N)/cos_wh_wo); G = MMIN(1, G); @@ -89,20 +89,20 @@ microfacet_reflection_sample int* type, double* pdf) { - struct microfacet_reflection* bxdf = data; + struct microfacet_reflection* bsdf = data; double dir[3]; double wh[3]; double pdf_wh; double R; ASSERT(data && wo && N && wi && pdf && type); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0); - ASSERT(bxdf->distrib && bxdf->fresnel); + ASSERT(bsdf->distrib && bsdf->fresnel); - ssf_microfacet_distribution_sample(bxdf->distrib, rng, wo, N, wh, &pdf_wh); + ssf_microfacet_distribution_sample(bsdf->distrib, rng, wo, N, wh, &pdf_wh); reflect(dir, wo, wh); *pdf = pdf_wh / (4.0*fabs(d3_dot(wo, wh))); *type = SSF_REFLECTION | SSF_GLOSSY; - R = d3_dot(dir, N) > 0 ? ssf_fresnel_eval(bxdf->fresnel, d3_dot(dir, wh)) : 0; + R = d3_dot(dir, N) > 0 ? ssf_fresnel_eval(bsdf->fresnel, d3_dot(dir, wh)) : 0; d3_set(wi, dir); return R; } @@ -111,15 +111,15 @@ static FINLINE double microfacet_reflection_pdf (void* data, const double wo[3], const double N[3], const double wi[3]) { - struct microfacet_reflection* bxdf = data; + struct microfacet_reflection* bsdf = data; double wh[3]; double pdf_wh; ASSERT(data && wo && N && wi); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_is_normalized(wi)); ASSERT(d3_dot(wo, N) > 0 && d3_dot(wi, N) > 0); - ASSERT(bxdf->distrib); + ASSERT(bsdf->distrib); d3_normalize(wh, d3_add(wh, wi, wo)); - pdf_wh = ssf_microfacet_distribution_pdf(bxdf->distrib, wo, N, wh); + pdf_wh = ssf_microfacet_distribution_pdf(bsdf->distrib, wo, N, wh); return pdf_wh / (4.0*fabs(d3_dot(wo, wh))); } @@ -136,22 +136,22 @@ microfacet2_reflection_sample int* type, double* pdf) { - struct microfacet_reflection* bxdf = data; + struct microfacet_reflection* bsdf = data; double dir[3]; double wh[3]; double p; double troughput = 1; ASSERT(data && wo && N && wi && pdf && type); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(N, wo) > 0.0); - ASSERT(bxdf->distrib); + ASSERT(bsdf->distrib); do { /* Sample a micro facet that front faces 'wo' */ - ssf_microfacet_distribution_sample(bxdf->distrib, rng, wo, N, wh, &p); + ssf_microfacet_distribution_sample(bsdf->distrib, rng, wo, N, wh, &p); } while(d3_dot(wo, wh) <= 0); reflect(dir, wo, wh); for(;;) { - troughput *= ssf_fresnel_eval(bxdf->fresnel, d3_dot(wh, dir)); + troughput *= ssf_fresnel_eval(bsdf->fresnel, d3_dot(wh, dir)); /* Do not take care of inter-reflections for sampled directions that point * outward the macro surface, i.e. simply stop the "random walk". */ @@ -160,7 +160,7 @@ microfacet2_reflection_sample /* Handle directions that point toward the macro surface has * inter-reflections */ do { /* Sample a microfacet that front faces 'wi' */ - ssf_microfacet_distribution_sample(bxdf->distrib, rng, dir, N, wh, &p); + ssf_microfacet_distribution_sample(bsdf->distrib, rng, dir, N, wh, &p); } while(d3_dot(dir, wh) <= 0); reflect(dir, dir, wh); } @@ -190,7 +190,7 @@ microfacet2_reflection_pdf /******************************************************************************* * Exported symbols ******************************************************************************/ -const struct ssf_bxdf_type ssf_microfacet_reflection = { +const struct ssf_bsdf_type ssf_microfacet_reflection = { microfacet_reflection_init, microfacet_reflection_release, microfacet_reflection_sample, @@ -200,7 +200,7 @@ const struct ssf_bxdf_type ssf_microfacet_reflection = { ALIGNOF(struct microfacet_reflection) }; -const struct ssf_bxdf_type ssf_microfacet2_reflection = { +const struct ssf_bsdf_type ssf_microfacet2_reflection = { microfacet_reflection_init, microfacet_reflection_release, microfacet2_reflection_sample, @@ -212,18 +212,18 @@ const struct ssf_bxdf_type ssf_microfacet2_reflection = { res_T ssf_microfacet_reflection_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, struct ssf_fresnel* fresnel, struct ssf_microfacet_distribution* distrib) { struct microfacet_reflection* microfacet; - if(!bxdf || !fresnel || !distrib) + if(!bsdf || !fresnel || !distrib) return RES_BAD_ARG; - if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_microfacet_reflection) - && !BXDF_TYPE_EQ(&bxdf->type, &ssf_microfacet2_reflection)) + if(!BSDF_TYPE_EQ(&bsdf->type, &ssf_microfacet_reflection) + && !BSDF_TYPE_EQ(&bsdf->type, &ssf_microfacet2_reflection)) return RES_BAD_ARG; - microfacet = bxdf->data; + microfacet = bsdf->data; if(microfacet->fresnel != fresnel) { if(microfacet->fresnel) SSF(fresnel_ref_put(fresnel)); SSF(fresnel_ref_get(fresnel)); diff --git a/src/ssf_specular_dielectric_dielectric_interface.c b/src/ssf_specular_dielectric_dielectric_interface.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssf.h" -#include "ssf_bxdf_c.h" +#include "ssf_bsdf_c.h" #include "ssf_optics.h" #include <rsys/double3.h> @@ -31,24 +31,24 @@ struct specular_dielectric_dielectric_interface { ******************************************************************************/ static res_T ssf_specular_dielectric_dielectric_interface_init - (struct mem_allocator* allocator, void* bxdf) + (struct mem_allocator* allocator, void* data) { - struct specular_dielectric_dielectric_interface* bsdf = bxdf; - ASSERT(bxdf); + struct specular_dielectric_dielectric_interface* bsdf = data; + ASSERT(bsdf); return ssf_fresnel_create (allocator, &ssf_fresnel_dielectric_dielectric, &bsdf->fresnel); } static void -ssf_specular_dielectric_dielectric_interface_release(void* bxdf) +ssf_specular_dielectric_dielectric_interface_release(void* data) { - struct specular_dielectric_dielectric_interface* bsdf = bxdf; + struct specular_dielectric_dielectric_interface* bsdf = data; SSF(fresnel_ref_put(bsdf->fresnel)); } static double ssf_specular_dielectric_dielectric_interface_sample - (void* bxdf, + (void* data, struct ssp_rng* rng, const double wo[3], const double N[3], @@ -56,14 +56,14 @@ ssf_specular_dielectric_dielectric_interface_sample int* type, double* pdf) { - struct specular_dielectric_dielectric_interface* bsdf = bxdf; + struct specular_dielectric_dielectric_interface* bsdf = data; struct ssf_fresnel* fresnel; double wt[3]; double *refracted; double cos_wo_N; double eta; /* Ratio of eta_i / eta_t */ double R; - ASSERT(bxdf && rng && wi && N && wo && type && pdf); + ASSERT(bsdf && rng && wi && N && wo && type && pdf); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); ASSERT(d3_dot(wo, N) > -1.e-6); (void)rng; @@ -97,24 +97,24 @@ ssf_specular_dielectric_dielectric_interface_sample static double ssf_specular_dielectric_dielectric_interface_eval - (void* bxdf, const double wo[3], const double N[3], const double wi[3]) + (void* bsdf, const double wo[3], const double N[3], const double wi[3]) { - (void)bxdf, (void)wo, (void)N, (void)wi; + (void)bsdf, (void)wo, (void)N, (void)wi; return 0.0; } static double ssf_specular_dielectric_dielectric_interface_pdf - (void* bxdf, const double wo[3], const double N[3], const double wi[3]) + (void* bsdf, const double wo[3], const double N[3], const double wi[3]) { - (void)bxdf, (void)wo, (void)N, (void)wi; + (void)bsdf, (void)wo, (void)N, (void)wi; return 0.0; } /******************************************************************************* * Exported symbols ******************************************************************************/ -const struct ssf_bxdf_type ssf_specular_dielectric_dielectric_interface = { +const struct ssf_bsdf_type ssf_specular_dielectric_dielectric_interface = { ssf_specular_dielectric_dielectric_interface_init, ssf_specular_dielectric_dielectric_interface_release, ssf_specular_dielectric_dielectric_interface_sample, @@ -126,21 +126,21 @@ const struct ssf_bxdf_type ssf_specular_dielectric_dielectric_interface = { res_T ssf_specular_dielectric_dielectric_interface_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, const double eta_i, const double eta_t) { - struct specular_dielectric_dielectric_interface* bsdf; + struct specular_dielectric_dielectric_interface* data; - if(!bxdf || eta_i <= 0 || eta_t <= 0) + if(!bsdf || eta_i <= 0 || eta_t <= 0) return RES_BAD_ARG; - if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_specular_dielectric_dielectric_interface)) + if(!BSDF_TYPE_EQ(&bsdf->type, &ssf_specular_dielectric_dielectric_interface)) return RES_BAD_ARG; - bsdf = bxdf->data; + data = bsdf->data; - bsdf->eta_i = eta_i; - bsdf->eta_t = eta_t; + data->eta_i = eta_i; + data->eta_t = eta_t; return RES_OK; } diff --git a/src/ssf_specular_reflection.c b/src/ssf_specular_reflection.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssf.h" -#include "ssf_bxdf_c.h" +#include "ssf_bsdf_c.h" #include "ssf_optics.h" #include <rsys/double3.h> @@ -27,19 +27,19 @@ struct specular_reflection { * Private functions ******************************************************************************/ static res_T -specular_reflection_init(struct mem_allocator* allocator, void* bxdf) +specular_reflection_init(struct mem_allocator* allocator, void* bsdf) { - ASSERT(bxdf); - (void)allocator, (void)bxdf; + ASSERT(bsdf); + (void)allocator, (void)bsdf; return RES_OK; } static void -specular_reflection_release(void* bxdf) +specular_reflection_release(void* data) { - struct specular_reflection* spec = bxdf; - ASSERT(spec); - if(spec->fresnel) SSF(fresnel_ref_put(spec->fresnel)); + struct specular_reflection* brdf = data; + ASSERT(data); + if(brdf->fresnel) SSF(fresnel_ref_put(brdf->fresnel)); } static double @@ -87,7 +87,7 @@ specular_reflection_pdf /******************************************************************************* * Exported symbols ******************************************************************************/ -const struct ssf_bxdf_type ssf_specular_reflection = { +const struct ssf_bsdf_type ssf_specular_reflection = { specular_reflection_init, specular_reflection_release, specular_reflection_sample, @@ -99,16 +99,16 @@ const struct ssf_bxdf_type ssf_specular_reflection = { res_T ssf_specular_reflection_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, struct ssf_fresnel* fresnel) { struct specular_reflection* spec; - if(!bxdf || !fresnel) + if(!bsdf || !fresnel) return RES_BAD_ARG; - if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_specular_reflection)) + if(!BSDF_TYPE_EQ(&bsdf->type, &ssf_specular_reflection)) return RES_BAD_ARG; - spec = bxdf->data; + spec = bsdf->data; if(spec->fresnel != fresnel) { if(spec->fresnel) SSF(fresnel_ref_put(spec->fresnel)); diff --git a/src/ssf_specular_transmission.c b/src/ssf_specular_transmission.c @@ -1,122 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2017 (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 "ssf_bxdf_c.h" -#include "ssf_optics.h" - -#include <rsys/double3.h> - -struct specular_transmission { - struct ssf_fresnel* fresnel; - double eta_i, eta_t; -}; - -/******************************************************************************* - * Private functions - ******************************************************************************/ -static res_T -specular_transmission_init - (struct mem_allocator* allocator, void* bxdf) -{ - struct specular_transmission* btdf = bxdf; - ASSERT(btdf); - return ssf_fresnel_create - (allocator, &ssf_fresnel_dielectric_dielectric, &btdf->fresnel); -} - -static void -specular_transmission_release(void* bxdf) -{ - struct specular_transmission* btdf = bxdf; - ASSERT(btdf); - if(btdf->fresnel) SSF(fresnel_ref_put(btdf->fresnel)); -} - -static double -specular_transmission_sample - (void* bxdf, - struct ssp_rng* rng, - const double wo[3], - const double N[3], - double wi[3], - int* type, - double* pdf) -{ - struct specular_transmission* btdf = bxdf; - double eta; - double cos_wi_N; - ASSERT(rng && wo && N && wi && type && pdf); - ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0); - (void)rng; - - SSF(fresnel_dielectric_dielectric_setup - (btdf->fresnel, btdf->eta_t, btdf->eta_i)); - - eta = btdf->eta_i / btdf->eta_t; - if(!refract(wi, wo, N, eta)) { /* Total internal reflection */ - reflect(wi, wo, N); - *pdf = INF; - *type = SSF_REFLECTION | SSF_SPECULAR; - return 0.0; - } - cos_wi_N = d3_dot(wi, N); - *pdf = INF; - *type = SSF_TRANSMISSION | SSF_SPECULAR; - return 1.0 - ssf_fresnel_eval(btdf->fresnel, fabs(cos_wi_N)); -} - -static double -specular_transmission_eval - (void* data, const double wo[3], const double N[3], const double wi[3]) -{ - (void)data, (void)wi, (void)N, (void)wo; - return 0.0; -} - -static double -specular_transmission_pdf - (void* data, const double wo[3], const double N[3], const double wi[3]) -{ - (void)data, (void)wi, (void)N, (void)wo; - return 0.0; -} - -/******************************************************************************* - * Exported symbols - ******************************************************************************/ -const struct ssf_bxdf_type ssf_specular_transmission = { - specular_transmission_init, - specular_transmission_release, - specular_transmission_sample, - specular_transmission_eval, - specular_transmission_pdf, - sizeof(struct specular_transmission), - ALIGNOF(struct specular_transmission) -}; - -res_T -ssf_specular_transmission_setup - (struct ssf_bxdf* bxdf, const double eta_i, const double eta_t) -{ - struct specular_transmission* btdf; - if(!bxdf || eta_i <= 0 || eta_t <= 0) return RES_BAD_ARG; - if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_specular_transmission)) return RES_BAD_ARG; - btdf = bxdf->data; - btdf->eta_i = eta_i; - btdf->eta_t = eta_t; - return RES_OK; -} - diff --git a/src/ssf_thin_specular_dielectric.c b/src/ssf_thin_specular_dielectric.c @@ -14,7 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssf.h" -#include "ssf_bxdf_c.h" +#include "ssf_bsdf_c.h" #include "ssf_optics.h" #include <rsys/double3.h> @@ -32,25 +32,24 @@ struct thin_specular_dielectric { * Private functions ******************************************************************************/ static res_T -thin_specular_dielectric_init - (struct mem_allocator* allocator, void* bxdf) +thin_specular_dielectric_init(struct mem_allocator* allocator, void* data) { - struct thin_specular_dielectric* bsdf = bxdf; - ASSERT(bxdf); + struct thin_specular_dielectric* bsdf = data; + ASSERT(bsdf); return ssf_fresnel_create (allocator, &ssf_fresnel_dielectric_dielectric, &bsdf->fresnel); } static void -thin_specular_dielectric_release(void* bxdf) +thin_specular_dielectric_release(void* data) { - struct thin_specular_dielectric* bsdf = bxdf; + struct thin_specular_dielectric* bsdf = data; SSF(fresnel_ref_put(bsdf->fresnel)); } static double thin_specular_dielectric_sample - (void* bxdf, + (void* data, struct ssp_rng* rng, const double wo[3], const double N[3], @@ -58,7 +57,7 @@ thin_specular_dielectric_sample int* type, double* pdf) { - struct thin_specular_dielectric* bsdf = bxdf; + struct thin_specular_dielectric* bsdf = data; struct ssf_fresnel* fresnel; double wt[3], tmp[3]; double cos_wo_N, cos_wt_N; @@ -67,7 +66,7 @@ thin_specular_dielectric_sample double R, T; double rho1, rho2, rho2_sqr; double tau, tau_sqr; - ASSERT(bxdf && rng && wi && N && wo && type && pdf); + ASSERT(bsdf && rng && wi && N && wo && type && pdf); ASSERT(d3_is_normalized(wo) && d3_is_normalized(N)); ASSERT(d3_dot(wo, N) > -1.e-6); (void)rng; @@ -124,24 +123,24 @@ thin_specular_dielectric_sample static double thin_specular_dielectric_eval - (void* bxdf, const double wo[3], const double N[3], const double wi[3]) + (void* bsdf, const double wo[3], const double N[3], const double wi[3]) { - (void)bxdf, (void)wo, (void)N, (void)wi; + (void)bsdf, (void)wo, (void)N, (void)wi; return 0.0; } static double thin_specular_dielectric_pdf - (void* bxdf, const double wo[3], const double N[3], const double wi[3]) + (void* bsdf, const double wo[3], const double N[3], const double wi[3]) { - (void)bxdf, (void)wo, (void)N, (void)wi; + (void)bsdf, (void)wo, (void)N, (void)wi; return 0.0; } /******************************************************************************* * Exported symbols ******************************************************************************/ -const struct ssf_bxdf_type ssf_thin_specular_dielectric = { +const struct ssf_bsdf_type ssf_thin_specular_dielectric = { thin_specular_dielectric_init, thin_specular_dielectric_release, thin_specular_dielectric_sample, @@ -153,26 +152,26 @@ const struct ssf_bxdf_type ssf_thin_specular_dielectric = { res_T ssf_thin_specular_dielectric_setup - (struct ssf_bxdf* bxdf, + (struct ssf_bsdf* bsdf, const double absorption, const double eta_i, const double eta_t, const double thickness) { - struct thin_specular_dielectric* bsdf; + struct thin_specular_dielectric* data; - if(!bxdf || thickness <= 0 || eta_i <= 0 || eta_t <= 0 || absorption < 0 + if(!bsdf || thickness <= 0 || eta_i <= 0 || eta_t <= 0 || absorption < 0 || absorption > 1) return RES_BAD_ARG; - if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_thin_specular_dielectric)) + if(!BSDF_TYPE_EQ(&bsdf->type, &ssf_thin_specular_dielectric)) return RES_BAD_ARG; - bsdf = bxdf->data; + data = bsdf->data; - bsdf->absorption = absorption; - bsdf->thickness = thickness; - bsdf->eta_i = eta_i; - bsdf->eta_t = eta_t; + data->absorption = absorption; + data->thickness = thickness; + data->eta_i = eta_i; + data->eta_t = eta_t; return RES_OK; } diff --git a/src/test_ssf_bsdf.c b/src/test_ssf_bsdf.c @@ -18,99 +18,196 @@ #include <rsys/double3.h> +static int bsdf_is_init = 0; + +struct ALIGN(64) bsdf { + uint32_t id; + struct ssp_rng* rng; + double wi[3]; + double wo[3]; + double N[3]; + double reflectivity; + double value; + double pdf; + double rho; +}; + +static res_T +bsdf_init(struct mem_allocator* allocator, void* bsdf) +{ + NCHECK(allocator, NULL); + NCHECK(bsdf, NULL); + CHECK(IS_ALIGNED(bsdf, 64), 1); + ((struct bsdf*)bsdf)->id = 0xDECAFBAD; + bsdf_is_init = 1; + return RES_OK; +} + +static void +bsdf_release(void* bsdf) +{ + NCHECK(bsdf, NULL); + CHECK(((struct bsdf*)bsdf)->id, 0xDECAFBAD); + bsdf_is_init = 0; +} + +static double +bsdf_sample + (void* bsdf, + struct ssp_rng* rng, + const double wo[3], + const double N[3], + double wi[3], + int* type, + double* pdf) +{ + struct bsdf* BxDF = bsdf; + NCHECK(BxDF, NULL); + CHECK(BxDF->rng, rng); + CHECK(d3_eq(BxDF->wo, wo), 1); + CHECK(d3_eq(BxDF->N, N), 1); + d3(wi, 1.0, 2.0, 3.0); + *type = 314; + *pdf = 4; + return BxDF->reflectivity; +} + +static double +bsdf_eval + (void* bsdf, + const double wo[3], + const double N[3], + const double wi[3]) +{ + struct bsdf* BxDF = bsdf; + NCHECK(BxDF, NULL); + NCHECK(wi, NULL); + NCHECK(wo, NULL); + CHECK(d3_eq(BxDF->wo, wo), 1); + CHECK(d3_eq(BxDF->N, N), 1); + CHECK(d3_eq(BxDF->wi, wi), 1); + return BxDF->value; +} + +static double +bsdf_pdf + (void* bsdf, + const double wo[3], + const double N[3], + const double wi[3]) +{ + struct bsdf* BxDF = bsdf; + NCHECK(BxDF, NULL); + NCHECK(wi, NULL); + NCHECK(wo, NULL); + CHECK(d3_eq(BxDF->wo, wo), 1); + CHECK(d3_eq(BxDF->N, N), 1); + CHECK(d3_eq(BxDF->wi, wi), 1); + return BxDF->pdf; +} + int main(int argc, char** argv) { - const size_t NSTEPS = 100000; struct mem_allocator allocator; struct ssp_rng* rng; + struct bsdf* data; struct ssf_bsdf* bsdf; - struct ssf_bxdf* bxdf; - struct ssf_bxdf* bxdf2; - struct ssf_fresnel* fresnel; - double wo[3], wi[3], pdf; + struct ssf_bsdf_type type = SSF_BXDF_TYPE_NULL; + double wo[3]; double N[3]; - double E, V, SE, R; - double sum, sqr_sum; - double sample[4]; - size_t i; - int type; + double wi[4]; + double pdf; + int i; (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(ssf_bsdf_create(NULL, NULL), RES_BAD_ARG); - CHECK(ssf_bsdf_create(&allocator, NULL), RES_BAD_ARG); - CHECK(ssf_bsdf_create(NULL, &bsdf), RES_OK); - CHECK(ssf_fresnel_create(&allocator, &ssf_fresnel_no_op, &fresnel), RES_OK); + type.init = bsdf_init; + type.release = bsdf_release; + type.sample = bsdf_sample; + type.eval = bsdf_eval; + type.pdf = bsdf_pdf; + type.sizeof_bsdf = sizeof(struct bsdf); + type.alignof_bsdf = ALIGNOF(struct bsdf); + + CHECK(ssf_bsdf_create(NULL, NULL, NULL), RES_BAD_ARG); + CHECK(ssf_bsdf_create(&allocator, NULL, NULL), RES_BAD_ARG); + CHECK(ssf_bsdf_create(NULL, &type, NULL), RES_BAD_ARG); + CHECK(ssf_bsdf_create(&allocator, &type, NULL), RES_BAD_ARG); + CHECK(ssf_bsdf_create(NULL, NULL, &bsdf), RES_BAD_ARG); + CHECK(ssf_bsdf_create(&allocator, NULL, &bsdf), RES_BAD_ARG); + + CHECK(bsdf_is_init, 0); + CHECK(ssf_bsdf_create(NULL, &type, &bsdf), RES_OK); + CHECK(bsdf_is_init, 1); CHECK(ssf_bsdf_ref_get(NULL), RES_BAD_ARG); CHECK(ssf_bsdf_ref_get(bsdf), RES_OK); CHECK(ssf_bsdf_ref_put(NULL), RES_BAD_ARG); CHECK(ssf_bsdf_ref_put(bsdf), RES_OK); + CHECK(bsdf_is_init, 1); CHECK(ssf_bsdf_ref_put(bsdf), RES_OK); + CHECK(bsdf_is_init, 0); - CHECK(ssf_bsdf_create(&allocator, &bsdf), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &ssf_specular_reflection, &bxdf), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &ssf_specular_reflection, &bxdf2), RES_OK); - CHECK(ssf_specular_reflection_setup(bxdf, fresnel), RES_OK); - CHECK(ssf_specular_reflection_setup(bxdf2, fresnel), RES_OK); - - CHECK(ssf_bsdf_add(NULL, NULL, -1.0), RES_BAD_ARG); - CHECK(ssf_bsdf_add(bsdf, NULL, -1.0), RES_BAD_ARG); - CHECK(ssf_bsdf_add(NULL, bxdf, -1.0), RES_BAD_ARG); - CHECK(ssf_bsdf_add(bsdf, bxdf, -1.0), RES_BAD_ARG); - CHECK(ssf_bsdf_add(NULL, NULL, 1), RES_BAD_ARG); - CHECK(ssf_bsdf_add(bsdf, NULL, 1), RES_BAD_ARG); - CHECK(ssf_bsdf_add(NULL, bxdf, 1), RES_BAD_ARG); - CHECK(ssf_bsdf_add(bsdf, bxdf, 1), RES_OK); - - d3_normalize(wo, d3(wo, 1, 1, 0)); + CHECK(ssf_bsdf_create(&allocator, &type, &bsdf), RES_OK); + CHECK(bsdf_is_init, 1); + CHECK(ssf_bsdf_ref_put(bsdf), RES_OK); + CHECK(bsdf_is_init, 0); + + type.init = NULL; + CHECK(ssf_bsdf_create(&allocator, &type, &bsdf), RES_BAD_ARG); + CHECK(bsdf_is_init, 0); + type.init = bsdf_init; + type.release = NULL; + CHECK(ssf_bsdf_create(&allocator, &type, &bsdf), RES_BAD_ARG); + CHECK(bsdf_is_init, 0); + type.release = bsdf_release; + type.sample = NULL; + CHECK(ssf_bsdf_create(&allocator, &type, &bsdf), RES_BAD_ARG); + CHECK(bsdf_is_init, 0); + type.sample = bsdf_sample; + type.alignof_bsdf = 3; + CHECK(ssf_bsdf_create(&allocator, &type, &bsdf), RES_BAD_ARG); + CHECK(bsdf_is_init, 0); + type.alignof_bsdf = ALIGNOF(struct bsdf); + CHECK(ssf_bsdf_create(&allocator, &type, &bsdf), RES_OK); + CHECK(bsdf_is_init, 1); + + CHECK(ssf_bsdf_get_data(NULL, NULL), RES_BAD_ARG); + CHECK(ssf_bsdf_get_data(bsdf, NULL), RES_BAD_ARG); + CHECK(ssf_bsdf_get_data(NULL, (void**)&data), RES_BAD_ARG); + CHECK(ssf_bsdf_get_data(bsdf, (void**)&data), RES_OK); + + CHECK(data->id, 0xDECAFBAD); + + d3_normalize(wo, d3(wo, -1, -1, 0)); d3(N, 0.0, 1.0, 0.0); - R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); - CHECK(type, SSF_SPECULAR | SSF_REFLECTION); - CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(wi, N)), 1.e-6), 1); - CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), 0); - CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), 0); - - CHECK(ssf_specular_reflection_setup(bxdf, fresnel), RES_OK); - R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); - CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(wi, N)), 1.e-6), 1); - CHECK(type, SSF_SPECULAR | SSF_REFLECTION); - - CHECK(ssf_bsdf_add(bsdf, bxdf2, 1), RES_OK); - - /* Estimate the BSDF rho. FIXME the following computation is certainly - * totally wrong */ - sum = 0; - sqr_sum = 0; - ssp_ran_hemisphere_uniform(rng, N, sample); - d3_set(wo, sample); - FOR_EACH(i, 0, NSTEPS) { - double weight = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); - CHECK(type, SSF_SPECULAR | SSF_REFLECTION); - CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), 0); - CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), 0); - sum += weight; - sqr_sum += weight*weight; - } - E = sum / (double)NSTEPS; - V = sqr_sum / (double)NSTEPS - E*E; - SE = sqrt(V / (double)NSTEPS); - CHECK(eq_eps(1, E, SE), 1); - - CHECK(ssf_bsdf_clear(NULL), RES_BAD_ARG); - CHECK(ssf_bsdf_clear(bsdf), RES_OK); - - CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf), 0.0); - CHECK(type, 0); - CHECK(pdf, 0.0); - + d3_set(data->wo, wo); + d3_set(data->N, N); + data->rng = rng; + data->reflectivity = 0.1234; + + CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &i, &pdf), 0.1234); + CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &i, &pdf), 0.1234); + CHECK(i, 314); + CHECK(pdf, 4); + + data->reflectivity = 0.314; + CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &i, &pdf), 0.314); + + d3_normalize(wi, wi); + d3_set(data->wi, wi); + data->value = 0.4567; + CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), data->value); + data->pdf = 0.890; + CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), data->pdf); + + CHECK(bsdf_is_init, 1); CHECK(ssf_bsdf_ref_put(bsdf), RES_OK); - CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); - CHECK(ssf_bxdf_ref_put(bxdf2), RES_OK); - CHECK(ssf_fresnel_ref_put(fresnel), RES_OK); + CHECK(bsdf_is_init, 0); + CHECK(ssp_rng_ref_put(rng), RES_OK); check_memory_allocator(&allocator); diff --git a/src/test_ssf_bxdf.c b/src/test_ssf_bxdf.c @@ -1,218 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2017 (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 bxdf_is_init = 0; - -struct ALIGN(64) bxdf { - uint32_t id; - struct ssp_rng* rng; - double wi[3]; - double wo[3]; - double N[3]; - double reflectivity; - double value; - double pdf; - double rho; -}; - -static res_T -bxdf_init(struct mem_allocator* allocator, void* bxdf) -{ - NCHECK(allocator, NULL); - NCHECK(bxdf, NULL); - CHECK(IS_ALIGNED(bxdf, 64), 1); - ((struct bxdf*)bxdf)->id = 0xDECAFBAD; - bxdf_is_init = 1; - return RES_OK; -} - -static void -bxdf_release(void* bxdf) -{ - NCHECK(bxdf, NULL); - CHECK(((struct bxdf*)bxdf)->id, 0xDECAFBAD); - bxdf_is_init = 0; -} - -static double -bxdf_sample - (void* bxdf, - struct ssp_rng* rng, - const double wo[3], - const double N[3], - double wi[3], - int* type, - double* pdf) -{ - struct bxdf* BxDF = bxdf; - NCHECK(BxDF, NULL); - CHECK(BxDF->rng, rng); - CHECK(d3_eq(BxDF->wo, wo), 1); - CHECK(d3_eq(BxDF->N, N), 1); - d3(wi, 1.0, 2.0, 3.0); - *type = 314; - *pdf = 4; - return BxDF->reflectivity; -} - -static double -bxdf_eval - (void* bxdf, - const double wo[3], - const double N[3], - const double wi[3]) -{ - struct bxdf* BxDF = bxdf; - NCHECK(BxDF, NULL); - NCHECK(wi, NULL); - NCHECK(wo, NULL); - CHECK(d3_eq(BxDF->wo, wo), 1); - CHECK(d3_eq(BxDF->N, N), 1); - CHECK(d3_eq(BxDF->wi, wi), 1); - return BxDF->value; -} - -static double -bxdf_pdf - (void* bxdf, - const double wo[3], - const double N[3], - const double wi[3]) -{ - struct bxdf* BxDF = bxdf; - NCHECK(BxDF, NULL); - NCHECK(wi, NULL); - NCHECK(wo, NULL); - CHECK(d3_eq(BxDF->wo, wo), 1); - CHECK(d3_eq(BxDF->N, N), 1); - CHECK(d3_eq(BxDF->wi, wi), 1); - return BxDF->pdf; -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct ssp_rng* rng; - struct bxdf* data; - struct ssf_bxdf* bxdf; - struct ssf_bxdf_type type = SSF_BXDF_TYPE_NULL; - double wo[3]; - double N[3]; - double wi[4]; - double pdf; - int i; - (void)argc, (void)argv; - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - - type.init = bxdf_init; - type.release = bxdf_release; - type.sample = bxdf_sample; - type.eval = bxdf_eval; - type.pdf = bxdf_pdf; - type.sizeof_bxdf = sizeof(struct bxdf); - type.alignof_bxdf = ALIGNOF(struct bxdf); - - CHECK(ssf_bxdf_create(NULL, NULL, NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_create(&allocator, NULL, NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_create(NULL, &type, NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_create(&allocator, &type, NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_create(NULL, NULL, &bxdf), RES_BAD_ARG); - CHECK(ssf_bxdf_create(&allocator, NULL, &bxdf), RES_BAD_ARG); - - CHECK(bxdf_is_init, 0); - CHECK(ssf_bxdf_create(NULL, &type, &bxdf), RES_OK); - CHECK(bxdf_is_init, 1); - - CHECK(ssf_bxdf_ref_get(NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_ref_get(bxdf), RES_OK); - CHECK(ssf_bxdf_ref_put(NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); - CHECK(bxdf_is_init, 1); - CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); - CHECK(bxdf_is_init, 0); - - CHECK(ssf_bxdf_create(&allocator, &type, &bxdf), RES_OK); - CHECK(bxdf_is_init, 1); - CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); - CHECK(bxdf_is_init, 0); - - type.init = NULL; - CHECK(ssf_bxdf_create(&allocator, &type, &bxdf), RES_BAD_ARG); - CHECK(bxdf_is_init, 0); - type.init = bxdf_init; - type.release = NULL; - CHECK(ssf_bxdf_create(&allocator, &type, &bxdf), RES_BAD_ARG); - CHECK(bxdf_is_init, 0); - type.release = bxdf_release; - type.sample = NULL; - CHECK(ssf_bxdf_create(&allocator, &type, &bxdf), RES_BAD_ARG); - CHECK(bxdf_is_init, 0); - type.sample = bxdf_sample; - type.alignof_bxdf = 3; - CHECK(ssf_bxdf_create(&allocator, &type, &bxdf), RES_BAD_ARG); - CHECK(bxdf_is_init, 0); - type.alignof_bxdf = ALIGNOF(struct bxdf); - CHECK(ssf_bxdf_create(&allocator, &type, &bxdf), RES_OK); - CHECK(bxdf_is_init, 1); - - CHECK(ssf_bxdf_get_data(NULL, NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_get_data(bxdf, NULL), RES_BAD_ARG); - CHECK(ssf_bxdf_get_data(NULL, (void**)&data), RES_BAD_ARG); - CHECK(ssf_bxdf_get_data(bxdf, (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); - data->rng = rng; - data->reflectivity = 0.1234; - - CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &i, &pdf), 0.1234); - CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &i, &pdf), 0.1234); - CHECK(i, 314); - CHECK(pdf, 4); - - data->reflectivity = 0.314; - CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &i, &pdf), 0.314); - - d3_normalize(wi, wi); - d3_set(data->wi, wi); - data->value = 0.4567; - CHECK(ssf_bxdf_eval(bxdf, wo, N, wi), data->value); - data->pdf = 0.890; - CHECK(ssf_bxdf_pdf(bxdf, wo, N, wi), data->pdf); - - CHECK(bxdf_is_init, 1); - CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); - CHECK(bxdf_is_init, 0); - - CHECK(ssp_rng_ref_put(rng), RES_OK); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); - return 0; -} - diff --git a/src/test_ssf_lambertian_reflection.c b/src/test_ssf_lambertian_reflection.c @@ -25,8 +25,8 @@ main(int argc, char** argv) const size_t NSTEPS = 100000; struct mem_allocator allocator; struct ssp_rng* rng; - struct ssf_bxdf* brdf; - struct ssf_bxdf* dummy; + struct ssf_bsdf* brdf; + struct ssf_bsdf* dummy; double E, SE, V; double sum; double sum_sqr; @@ -42,8 +42,8 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &ssf_lambertian_reflection, &brdf), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &ssf_lambertian_reflection, &brdf), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &bsdf_dummy, &dummy), RES_OK); CHECK(ssf_lambertian_reflection_setup(NULL, -1.0), RES_BAD_ARG); CHECK(ssf_lambertian_reflection_setup(brdf, -1.0), RES_BAD_ARG); @@ -55,13 +55,13 @@ main(int argc, char** argv) d3(N, 0.0, 0.0, 1.0); d3_normalize(wo, d3(wo, 1.0, 0.0, 1.0)); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(wi[2]/PI, pdf, 1.e-6), 1); CHECK(R, 0); CHECK(type, SSF_DIFFUSE|SSF_REFLECTION); CHECK(ssf_lambertian_reflection_setup(brdf, 0.7), RES_OK); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(R, 0.7, 1.e-6), 1); CHECK(eq_eps(pdf, d3_dot(wi, N)/PI, 1.e-6), 1); CHECK(type, SSF_DIFFUSE|SSF_REFLECTION); @@ -77,7 +77,7 @@ main(int argc, char** argv) sum = sum_sqr = 0; FOR_EACH(i, 0, NSTEPS) { double cos_wi_N; - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf) / PI; + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf) / PI; cos_wi_N = d3_dot(wi, N); CHECK(eq_eps(R, 0.7/PI, 1.e-6), 1); CHECK(eq_eps(cos_wi_N/PI, pdf, 1.e-6), 1); @@ -95,7 +95,7 @@ main(int argc, char** argv) double cos_wi_N; double w; - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf)/PI; + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf)/PI; cos_wi_N = d3_dot(wi, N); CHECK(eq_eps(R, 0.7/PI, 1.e-6), 1); CHECK(eq_eps(cos_wi_N/PI, pdf, 1.e-6), 1); @@ -113,15 +113,15 @@ main(int argc, char** argv) FOR_EACH(i, 0, NSTEPS) { double val; - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(R, 0.7, 1.e-6), 1); - val = ssf_bxdf_eval(brdf, wo, N, wi) * d3_dot(wi, N); + val = ssf_bsdf_eval(brdf, wo, N, wi) * d3_dot(wi, N); CHECK(eq_eps(val, R * pdf, 1.e-6), 1); CHECK(type, SSF_DIFFUSE|SSF_REFLECTION); } - CHECK(ssf_bxdf_ref_put(brdf), RES_OK); - CHECK(ssf_bxdf_ref_put(dummy), RES_OK); + CHECK(ssf_bsdf_ref_put(brdf), RES_OK); + CHECK(ssf_bsdf_ref_put(dummy), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); check_memory_allocator(&allocator); diff --git a/src/test_ssf_microfacet_reflection.c b/src/test_ssf_microfacet_reflection.c @@ -23,8 +23,8 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct ssf_bxdf* bxdf; - struct ssf_bxdf* dummy; + struct ssf_bsdf* bsdf; + struct ssf_bsdf* dummy; struct ssf_fresnel* F; struct ssf_microfacet_distribution* D; struct ssp_rng* rng; @@ -35,8 +35,8 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &ssf_microfacet2_reflection, &bxdf), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &ssf_microfacet2_reflection, &bsdf), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &bsdf_dummy, &dummy), RES_OK); CHECK(ssf_fresnel_create(&allocator, &ssf_fresnel_no_op, &F), RES_OK); CHECK(ssf_microfacet_distribution_create (&allocator, &ssf_beckmann_distribution, &D), RES_OK); @@ -44,13 +44,13 @@ main(int argc, char** argv) CHECK(ssf_beckmann_distribution_setup(D, 0.9), RES_OK); CHECK(ssf_microfacet_reflection_setup(NULL, NULL, NULL), RES_BAD_ARG); - CHECK(ssf_microfacet_reflection_setup(bxdf, NULL, NULL), RES_BAD_ARG); + CHECK(ssf_microfacet_reflection_setup(bsdf, NULL, NULL), RES_BAD_ARG); CHECK(ssf_microfacet_reflection_setup(NULL, F, NULL), RES_BAD_ARG); - CHECK(ssf_microfacet_reflection_setup(bxdf, F, NULL), RES_BAD_ARG); + CHECK(ssf_microfacet_reflection_setup(bsdf, F, NULL), RES_BAD_ARG); CHECK(ssf_microfacet_reflection_setup(NULL, NULL, D), RES_BAD_ARG); - CHECK(ssf_microfacet_reflection_setup(bxdf, NULL, D), RES_BAD_ARG); + CHECK(ssf_microfacet_reflection_setup(bsdf, NULL, D), RES_BAD_ARG); CHECK(ssf_microfacet_reflection_setup(NULL, F, D), RES_BAD_ARG); - CHECK(ssf_microfacet_reflection_setup(bxdf, F, D), RES_OK); + CHECK(ssf_microfacet_reflection_setup(bsdf, F, D), RES_OK); /* Check energy conservation */ ssp_ran_sphere_uniform(rng, N); @@ -58,13 +58,13 @@ main(int argc, char** argv) FOR_EACH(i, 0, NSTEPS) { double wi[3], pdf; int type; - CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &type, &pdf), 1); + CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf), 1); CHECK(type, SSF_GLOSSY | SSF_REFLECTION); CHECK(d3_dot(wi, N) > 0, 1); } - CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); - CHECK(ssf_bxdf_ref_put(dummy), RES_OK); + CHECK(ssf_bsdf_ref_put(bsdf), RES_OK); + CHECK(ssf_bsdf_ref_put(dummy), RES_OK); CHECK(ssf_fresnel_ref_put(F), RES_OK); CHECK(ssf_microfacet_distribution_ref_put(D), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); diff --git a/src/test_ssf_specular_reflection.c b/src/test_ssf_specular_reflection.c @@ -24,8 +24,8 @@ main(int argc, char** argv) const size_t NSTEPS = 100000; struct mem_allocator allocator; struct ssp_rng* rng; - struct ssf_bxdf* brdf; - struct ssf_bxdf* dummy; + struct ssf_bsdf* brdf; + struct ssf_bsdf* dummy; struct ssf_fresnel* fresnel; double wo[3], wi[3]; double N[3]; @@ -37,8 +37,8 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &ssf_specular_reflection, &brdf), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &ssf_specular_reflection, &brdf), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &bsdf_dummy, &dummy), RES_OK); CHECK(ssf_fresnel_create (&allocator, &ssf_fresnel_dielectric_dielectric, &fresnel), RES_OK); CHECK(ssf_fresnel_dielectric_dielectric_setup(fresnel, 0.7, 1), RES_OK); @@ -51,31 +51,31 @@ main(int argc, char** argv) d3(N, 0.0, 1.0, 0.0); d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0)); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1); CHECK(IS_INF(pdf), 1); CHECK(type, SSF_SPECULAR|SSF_REFLECTION); d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0)); CHECK(ssf_specular_reflection_setup(brdf, fresnel), RES_OK); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1); CHECK(type, SSF_SPECULAR|SSF_REFLECTION); - CHECK(ssf_bxdf_eval(brdf, wo, N, wi), 0.0); - CHECK(ssf_bxdf_pdf(brdf, wo, N, wi), 0.0); + CHECK(ssf_bsdf_eval(brdf, wo, N, wi), 0.0); + CHECK(ssf_bsdf_pdf(brdf, wo, N, wi), 0.0); d3(wo, 0.0, 1.0, 0.0); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(d3(wo, 0.0, 1.0, 0.0), wi, 1.e-6), 1); CHECK(type, SSF_SPECULAR|SSF_REFLECTION); d3_normalize(wo, d3(wo, -1.0, 1.0, 0.0)); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1); @@ -85,17 +85,17 @@ main(int argc, char** argv) wo[1] = ssp_rng_uniform_double(rng, 0, 1); wo[2] = ssp_rng_uniform_double(rng, -1, 1); d3_normalize(wo, wo); - R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(brdf, rng, wo, N, wi, &type, &pdf); CHECK(type, SSF_SPECULAR|SSF_REFLECTION); FOR_EACH(i, 0, NSTEPS) { - CHECK(eq_eps(ssf_bxdf_sample + CHECK(eq_eps(ssf_bsdf_sample (brdf, rng, wo, N, wi, &type, &pdf), R, 1.e-6), 1); CHECK(type, SSF_SPECULAR|SSF_REFLECTION); } - CHECK(ssf_bxdf_ref_put(brdf), RES_OK); - CHECK(ssf_bxdf_ref_put(dummy), RES_OK); + CHECK(ssf_bsdf_ref_put(brdf), RES_OK); + CHECK(ssf_bsdf_ref_put(dummy), RES_OK); CHECK(ssf_fresnel_ref_put(fresnel), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); diff --git a/src/test_ssf_thin_specular_dielectric.c b/src/test_ssf_thin_specular_dielectric.c @@ -24,8 +24,8 @@ main(int argc, char** argv) const size_t NSTEPS = 1000000; struct mem_allocator allocator; struct ssp_rng* rng; - struct ssf_bxdf* bsdf; - struct ssf_bxdf* dummy; + struct ssf_bsdf* bsdf; + struct ssf_bsdf* dummy; double wo[3], wi[3]; double N[3]; double tmp[3]; @@ -41,9 +41,9 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(ssf_bxdf_create + CHECK(ssf_bsdf_create (&allocator, &ssf_thin_specular_dielectric, &bsdf), RES_OK); - CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK); + CHECK(ssf_bsdf_create(&allocator, &bsdf_dummy, &dummy), RES_OK); #define SETUP ssf_thin_specular_dielectric_setup CHECK(SETUP(NULL, -1, 0, 0, -1), RES_BAD_ARG); @@ -83,25 +83,25 @@ main(int argc, char** argv) d3(N, 0.0, 1.0, 0.0); d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0)); - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); NCHECK(R, 0); NCHECK(type & SSF_SPECULAR, 0); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6) || d3_eq_eps(wi, d3(tmp, -wo[0], -wo[1], 0), 1.e-6), 1); - CHECK(ssf_bxdf_eval(bsdf, wo, N, wi), 0.0); - CHECK(ssf_bxdf_pdf(bsdf, wo, N, wi), 0.0); + CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), 0.0); + CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), 0.0); d3(wo, 0.0, 1.0, 0.0); - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); NCHECK(R, 0); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], -wo[1], 0), 1.e-6), 1); CHECK(type, SSF_SPECULAR | SSF_TRANSMISSION); d3(wo, 1.0, 0.0, 0.0); - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); NCHECK(R, 0); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6), 1); @@ -110,13 +110,13 @@ main(int argc, char** argv) /* Check total internal reflection, i.e. no transmission */ d3_normalize(wo, d3(wo, 1, 0.0000001, 0)); CHECK(ssf_thin_specular_dielectric_setup(bsdf, 0, 1.4, 1.0, 1), RES_OK); - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); CHECK(R, 1); CHECK(IS_INF(pdf), 1); CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6), 1); CHECK(type, SSF_SPECULAR | SSF_REFLECTION); FOR_EACH(i, 0, NSTEPS) { - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); CHECK(type & SSF_REFLECTION, 1); CHECK(R, 1); } @@ -126,7 +126,7 @@ main(int argc, char** argv) SR2 = ST2 = 0; d3(wo, 0.0, 1.0, 0.0); FOR_EACH(i, 0, NSTEPS) { - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); if (type & SSF_TRANSMISSION) { ST += R; ST2 += R*R; } else { @@ -155,7 +155,7 @@ main(int argc, char** argv) d3_minus(refract, wo); FOR_EACH(i, 0, NSTEPS) { - R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); + R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf); NCHECK(R, 0); CHECK(IS_INF(pdf), 1); if(d3_eq_eps(wi, reflect, 1.e-6)) { @@ -168,8 +168,8 @@ main(int argc, char** argv) } CHECK(ssp_rng_ref_put(rng), RES_OK); - CHECK(ssf_bxdf_ref_put(bsdf), RES_OK); - CHECK(ssf_bxdf_ref_put(dummy), RES_OK); + CHECK(ssf_bsdf_ref_put(bsdf), RES_OK); + CHECK(ssf_bsdf_ref_put(dummy), RES_OK); return 0; } diff --git a/src/test_ssf_utils.h b/src/test_ssf_utils.h @@ -29,24 +29,24 @@ #endif /******************************************************************************* - * Dummy BxDF type + * Dummy BSDF type ******************************************************************************/ static res_T -bxdf_dummy_init(struct mem_allocator* allocator, void* bxdf) +bsdf_dummy_init(struct mem_allocator* allocator, void* bsdf) { - (void)allocator, (void)bxdf; + (void)allocator, (void)bsdf; return RES_OK; } static void -bxdf_dummy_release(void* bxdf) +bsdf_dummy_release(void* bsdf) { - (void)bxdf; + (void)bsdf; } static double -bxdf_dummy_sample - (void* bxdf, +bsdf_dummy_sample + (void* bsdf, struct ssp_rng* rng, const double w[3], const double N[3], @@ -54,38 +54,38 @@ bxdf_dummy_sample int* type, double* pdf) { - (void)bxdf, (void)rng, (void)w, (void)N, (void)dir, (void)type, (void)pdf; + (void)bsdf, (void)rng, (void)w, (void)N, (void)dir, (void)type, (void)pdf; return 0.0; } static double -bxdf_dummy_eval - (void* bxdf, +bsdf_dummy_eval + (void* bsdf, const double wo[3], const double N[3], const double wi[3]) { - (void)bxdf, (void)wo, (void)N, (void)wi; + (void)bsdf, (void)wo, (void)N, (void)wi; return 0.0; } static double -bxdf_dummy_pdf - (void* bxdf, +bsdf_dummy_pdf + (void* bsdf, const double wo[3], const double N[3], const double wi[3]) { - (void)bxdf, (void)wo, (void)N, (void)wi; + (void)bsdf, (void)wo, (void)N, (void)wi; return 0.0; } -static const struct ssf_bxdf_type bxdf_dummy = { - bxdf_dummy_init, - bxdf_dummy_release, - bxdf_dummy_sample, - bxdf_dummy_eval, - bxdf_dummy_pdf, +static const struct ssf_bsdf_type bsdf_dummy = { + bsdf_dummy_init, + bsdf_dummy_release, + bsdf_dummy_sample, + bsdf_dummy_eval, + bsdf_dummy_pdf, 0, 1 };