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 863ed1ee241b1aae6870a7d30cc721f7341e6ef4
parent e5495a3b45c2da69df4101938b7b1b390fc84a6c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 22 Sep 2016 12:08:55 +0200

Add and test the "rho" B<x|S>DF function

rho(wo) is the integral over 2PI of B<x|S>DF(wo, wi) |wi.N|

Diffstat:
Msrc/ssf.h | 26++++++++++++++++++++++++++
Msrc/ssf_bsdf_view.c | 26++++++++++++++++++++------
Msrc/ssf_bxdf.c | 8++++++++
Msrc/ssf_bxdf_c.h | 1+
Msrc/ssf_lambertian_reflection.c | 9+++++++++
Msrc/ssf_microfacet_reflection.c | 9+++++++++
Msrc/ssf_specular_reflection.c | 9+++++++++
Msrc/test_ssf_bsdf_view.c | 4++++
Msrc/test_ssf_bxdf.c | 30++++++++++++++++++++++--------
Msrc/test_ssf_fresnel.c | 2+-
Msrc/test_ssf_utils.h | 8++++++++
11 files changed, 117 insertions(+), 15 deletions(-)

diff --git a/src/ssf.h b/src/ssf.h @@ -78,9 +78,18 @@ struct ssf_bxdf_type { const double N[3], /* Normalized surface normal */ const double wi[3]);/* Normalized incoming direction */ + /* rho(wo) = \int_{2\pi} BxDF(wo,wi) |wi.N| dwi + * rho(wo) P(wi,wo) = BxDF(wo,wi) |wi.N|; with \int_{2\pi} P(wo,wi) dwi = 1 */ + double + (*rho) + (void* bxdf, + const double wo[3]); + size_t sizeof_bxdf; /* In Bytes */ size_t alignof_bxdf; /* In Bytes */ }; +#define SSF_BXDF_TYPE_NULL__ {NULL, NULL, NULL, NULL, NULL, NULL, 0, 1} +static const struct ssf_bxdf_type SSF_BXDF_TYPE_NULL = SSF_BXDF_TYPE_NULL__; /* Generic Fresnel term descriptor */ struct ssf_fresnel_type { @@ -95,6 +104,9 @@ struct ssf_fresnel_type { size_t sizeof_fresnel; /* In Bytes */ size_t alignof_fresnel; /* In Bytes */ }; +#define SSF_FRESNEL_TYPE_NULL__ {NULL, NULL, NULL, 0, 1} +static const struct ssf_fresnel_type SSF_FRESNEL_TYPE_NULL = + SSF_FRESNEL_TYPE_NULL__; /* Generic descriptor of a microfacet distribution */ struct ssf_microfacet_distribution_type { @@ -128,6 +140,10 @@ struct ssf_microfacet_distribution_type { size_t sizeof_distribution; /* In Bytes */ size_t alignof_distribution; /* In Bytes */ }; +#define SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__ \ + {NULL, NULL, NULL, NULL, NULL, 0, 1} +static const struct ssf_microfacet_distribution_type +SSF_MICROFACET_DISTRIBUTION_TYPE_NULL = SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__; BEGIN_DECLS @@ -216,6 +232,11 @@ ssf_bsdf_view_pdf const double N[3], /* Normalized surface normal */ const double wi[3]); /* Normalized outgoing direction */ +SSF_API double /* \int_{2\pi} BSDF(wi, wo) |wi.N| dwi */ +ssf_bsdf_view_rho + (struct ssf_bsdf_view* view, + const double wo[3]); + /******************************************************************************* * BxDF API - Bidirectional <Reflectance|Transmittance> distribution function. * Describes how the light is reflected|transmitted by a surface. Note that by @@ -260,6 +281,11 @@ ssf_bxdf_pdf const double N[3], /* Normalized surface normal */ const double wi[3]);/* Normalized incoming dir. Point outward the surface */ +SSF_API double /* \int_{2\pi} BxDF(wi, wo) |wi.N| dwi */ +ssf_bxdf_rho + (struct ssf_bxdf* bxdf, + const double wo[3]); + /* 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 diff --git a/src/ssf_bsdf_view.c b/src/ssf_bsdf_view.c @@ -177,9 +177,9 @@ ssf_bsdf_view_sample double ssf_bsdf_view_eval (struct ssf_bsdf_view* view, - const double wi[3], + const double wo[3], const double N[3], - const double wo[3]) + const double wi[3]) { double R = 0; size_t i; @@ -187,7 +187,7 @@ ssf_bsdf_view_eval ASSERT(d3_is_normalized(wi) && d3_is_normalized(wo)); FOR_EACH(i, 0, view->ncomponents) { - R += ssf_bxdf_eval(view->components[i], wi, N, wo) * view->probas[i]; + R += ssf_bxdf_eval(view->components[i], wo, N, wi) * view->probas[i]; } return R; } @@ -195,9 +195,9 @@ ssf_bsdf_view_eval double ssf_bsdf_view_pdf (struct ssf_bsdf_view* view, - const double wi[3], + const double wo[3], const double N[3], - const double wo[3]) + const double wi[3]) { double pdf = 0; size_t i; @@ -205,11 +205,25 @@ ssf_bsdf_view_pdf ASSERT(d3_is_normalized(wi) && d3_is_normalized(wo)); FOR_EACH(i, 0, view->ncomponents) { - pdf += ssf_bxdf_pdf(view->components[i], wi, N, wo) * view->probas[i]; + pdf += ssf_bxdf_pdf(view->components[i], wo, N, wi) * view->probas[i]; } return pdf; } +double +ssf_bsdf_view_rho + (struct ssf_bsdf_view* view, + const double wo[3]) +{ + double rho = 0; + size_t i; + ASSERT(view && wo); + FOR_EACH(i, 0, view->ncomponents) { + rho += ssf_bxdf_rho(view->components[i], wo) * view->probas[i]; + } + return rho; +} + /******************************************************************************* * Local functions ******************************************************************************/ diff --git a/src/ssf_bxdf.c b/src/ssf_bxdf.c @@ -34,6 +34,7 @@ check_bxdf_type(const struct ssf_bxdf_type* type) && type->sample && type->eval && type->pdf + && type->rho && IS_POW2(type->alignof_bxdf); } @@ -152,6 +153,13 @@ ssf_bxdf_pdf return bxdf->type.pdf(bxdf->data, wo, N, wi); } +double +ssf_bxdf_rho(struct ssf_bxdf* bxdf, const double wo[3]) +{ + ASSERT(bxdf && wo && d3_is_normalized(wo)); + return bxdf->type.rho(bxdf->data, wo); +} + res_T ssf_bxdf_get_data(struct ssf_bxdf* bxdf, void** data) { diff --git a/src/ssf_bxdf_c.h b/src/ssf_bxdf_c.h @@ -36,6 +36,7 @@ struct ssf_bxdf { && (A)->sample == (B)->sample \ && (A)->eval == (B)->eval \ && (A)->pdf == (B)->pdf \ + && (A)->rho == (B)->rho \ && (A)->sizeof_bxdf == (B)->sizeof_bxdf \ && (A)->alignof_bxdf == (B)->alignof_bxdf) diff --git a/src/ssf_lambertian_reflection.c b/src/ssf_lambertian_reflection.c @@ -93,6 +93,14 @@ lambertian_reflection_pdf return cos_wi_N <= 0.0 ? 0.0 : cos_wi_N / PI; } +static double +lambertian_reflection_rho(void* data, const double wo[3]) +{ + ASSERT(data && wo); + (void)wo; + return ((struct lambertian_reflection*)data)->reflectivity; +} + /******************************************************************************* * Exorted symbols ******************************************************************************/ @@ -102,6 +110,7 @@ const struct ssf_bxdf_type ssf_lambertian_reflection = { lambertian_reflection_sample, lambertian_reflection_eval, lambertian_reflection_pdf, + lambertian_reflection_rho, sizeof(struct lambertian_reflection), ALIGNOF(struct lambertian_reflection) }; diff --git a/src/ssf_microfacet_reflection.c b/src/ssf_microfacet_reflection.c @@ -124,6 +124,14 @@ microfacet_reflection_pdf return pdf_wh / (4.0*fabs(d3_dot(wo, wh))); /* TODO check this */ } +static FINLINE double +microfacet_reflection_rho(void* data, const double wo[3]) +{ + ASSERT(data && wo); + (void)data, (void)wo; + return 0; /* TODO */ +} + /******************************************************************************* * Exported symbols ******************************************************************************/ @@ -133,6 +141,7 @@ const struct ssf_bxdf_type ssf_microfacet_reflection = { microfacet_reflection_sample, microfacet_reflection_eval, microfacet_reflection_pdf, + microfacet_reflection_rho, sizeof(struct microfacet_reflection), ALIGNOF(struct microfacet_reflection) }; diff --git a/src/ssf_specular_reflection.c b/src/ssf_specular_reflection.c @@ -80,6 +80,14 @@ specular_reflection_pdf return 0.0; } +static double +specular_reflection_rho(void* data, const double wo[3]) +{ + ASSERT(data && wo); + (void)wo; + return ((struct specular_reflection*)data)->reflectivity; +} + /******************************************************************************* * Exported symbols ******************************************************************************/ @@ -89,6 +97,7 @@ const struct ssf_bxdf_type ssf_specular_reflection = { specular_reflection_sample, specular_reflection_eval, specular_reflection_pdf, + specular_reflection_rho, sizeof(struct specular_reflection), ALIGNOF(struct specular_reflection) }; diff --git a/src/test_ssf_bsdf_view.c b/src/test_ssf_bsdf_view.c @@ -30,6 +30,7 @@ main(int argc, char** argv) double N[3], wi[3], wo[3]; double pdf; double R; + double rho; double E, V, SE; double sum, sqr_sum; size_t i; @@ -89,6 +90,9 @@ main(int argc, char** argv) SE = sqrt(V / (double)NSTEPS); CHECK(eq_eps((0.1234+0.6789) * 0.5, E, SE), 1); + rho = ssf_bsdf_view_rho(view, wo); + CHECK(eq_eps(rho, (0.1234+0.6789)*0.5, 1.e-6), 1); + CHECK(ssf_bsdf_view_ref_get(NULL), RES_BAD_ARG); CHECK(ssf_bsdf_view_ref_get(view), RES_OK); CHECK(ssf_bsdf_view_ref_put(NULL), RES_BAD_ARG); diff --git a/src/test_ssf_bxdf.c b/src/test_ssf_bxdf.c @@ -30,6 +30,7 @@ struct ALIGN(64) bxdf { double reflectivity; double value; double pdf; + double rho; }; static res_T @@ -106,13 +107,22 @@ bxdf_pdf return BxDF->pdf; } +static double +bxdf_rho(void* bxdf, const double wo[3]) +{ + struct bxdf* BxDF = bxdf; + NCHECK(BxDF, NULL); + CHECK(d3_eq(BxDF->wo, wo), 1); + return BxDF->rho; +} + int main(int argc, char** argv) { struct mem_allocator allocator; struct bxdf* data; struct ssf_bxdf* bxdf; - struct ssf_bxdf_type type; + struct ssf_bxdf_type type = SSF_BXDF_TYPE_NULL; double wo[3]; double N[3]; double wi[4]; @@ -125,6 +135,7 @@ main(int argc, char** argv) type.release = bxdf_release; type.sample = bxdf_sample; type.eval = bxdf_eval; + type.rho = bxdf_rho; type.pdf = bxdf_pdf; type.sizeof_bxdf = sizeof(struct bxdf); type.alignof_bxdf = ALIGNOF(struct bxdf); @@ -185,23 +196,26 @@ main(int argc, char** argv) d3_set(data->N, N); data->u = 0.0; data->v = 0.0; - data->reflectivity = 1.234; + data->reflectivity = 0.1234; - CHECK(ssf_bxdf_sample(bxdf, 0, 0, wo, N, wi, &pdf), 1.234); + CHECK(ssf_bxdf_sample(bxdf, 0, 0, wo, N, wi, &pdf), 0.1234); data->u = 0.5; data->v = 0.5; - CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 1.234); + CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 0.1234); - data->reflectivity = 3.14; - CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 3.14); + data->reflectivity = 0.314; + CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 0.314); d3_normalize(wi, wi); d3_set(data->wi, wi); - data->value = 4.567; + data->value = 0.4567; CHECK(ssf_bxdf_eval(bxdf, wo, N, wi), data->value); - data->pdf = 8.90; + data->pdf = 0.890; CHECK(ssf_bxdf_pdf(bxdf, wo, N, wi), data->pdf); + data->rho = 0.314; + CHECK(ssf_bxdf_rho(bxdf, wo), data->rho); + CHECK(bxdf_is_init, 1); CHECK(ssf_bxdf_ref_put(bxdf), RES_OK); CHECK(bxdf_is_init, 0); diff --git a/src/test_ssf_fresnel.c b/src/test_ssf_fresnel.c @@ -59,7 +59,7 @@ main(int argc, char** argv) struct mem_allocator allocator; struct fresnel* data; struct ssf_fresnel* fresnel; - struct ssf_fresnel_type type; + struct ssf_fresnel_type type = SSF_FRESNEL_TYPE_NULL; (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator); diff --git a/src/test_ssf_utils.h b/src/test_ssf_utils.h @@ -71,12 +71,20 @@ bxdf_dummy_pdf return 0.0; } +static double +bxdf_dummy_rho(void* bxdf, const double wo[3]) +{ + (void)bxdf, (void)wo; + 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, + bxdf_dummy_rho, 0, 1 };