star-phor

Radiative transfer solver for photoreactors.
git clone https://www.edstar.cnrs.fr/git/star-phor.git
Log | Files | Refs | README | LICENSE

commit 717573681135dff7085564931f353d23e6530bd9
parent caff45f6a6d99beeeff7c85b0ed9bbbeac7e1933
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Fri, 27 Feb 2026 16:41:01 +0100

Implement KEEP_CURRENT_DIR BTDF and update path sampling

Implement a KEEP_CURRENT_DIR BTDF in which the transmitted direction wi
is identical to the outgoing direction wo.

Although this behavior could be handled as a special case without
needing a dedicated bsdf, we define it as a proper BTDF to ensure
consistent integration with the existing workflow (i.e., instantiating
and setting up an ssf_bsdf struct and using it to sample the outgoing
direction).

The new BTDF has been integrated into the path sampling routine.

Diffstat:
Msrc/sphor_ran_bsdf.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+), 0 deletions(-)

diff --git a/src/sphor_ran_bsdf.c b/src/sphor_ran_bsdf.c @@ -127,6 +127,109 @@ const struct ssf_bsdf_type lambertian_transmission = { ALIGNOF(struct lambertian_transmission) }; +/* BTDF KEEP_CURRENT_DIR */ +struct keep_current_dir_transmission { + struct ssf_fresnel* fresnel; +}; + +static void +keep_current_dir_transmission_release + (void* data) +{ + struct keep_current_dir_transmission* btdf = data; + ASSERT(data); + if (btdf->fresnel) SSF(fresnel_ref_put(btdf->fresnel)); +} + +static double +keep_current_dir_transmission_sample + (void* data, + struct ssp_rng* rng, + const double wo[3], + const double N[3], + double wi[3], + int* type, + double* pdf) +{ + struct keep_current_dir_transmission* btdf = data; + double cos_wo_N; + + ASSERT(NULL != data); + ASSERT(NULL != rng); + ASSERT(NULL != N); + ASSERT(NULL != wi); + ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0); + (void)rng; + + /* In ssf convention, wo points outwards the surface */ + d3_minus(wi, wo); + if (pdf) *pdf = INF; + if (type) *type = SSF_TRANSMISSION; + + cos_wo_N = d3_dot(wo, N); + return 1 - ssf_fresnel_eval(btdf->fresnel, cos_wo_N); +} + +static double +keep_current_dir_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 +keep_current_dir_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; +} + +static res_T +keep_current_dir_transmission_setup + (struct ssf_bsdf* bsdf, + struct ssf_fresnel* fresnel) +{ + void* ptr = NULL; + res_T res = RES_OK; + + ASSERT(NULL != bsdf); + ASSERT(NULL != fresnel); + + ssf_bsdf_get_data(bsdf, &ptr); + struct keep_current_dir_transmission* data = ptr; + + if (data->fresnel != fresnel) { + if (NULL != data->fresnel) { + res = ssf_fresnel_ref_put(data->fresnel); + if (RES_OK != res) { return res; } + } + res = ssf_fresnel_ref_get(fresnel); + if (RES_OK != res) { return res; } + + data->fresnel = fresnel; + } + + return RES_OK; +} + +const struct ssf_bsdf_type keep_current_dir_transmission = { + NULL, + keep_current_dir_transmission_release, + keep_current_dir_transmission_sample, + keep_current_dir_transmission_eval, + keep_current_dir_transmission_pdf, + sizeof(struct keep_current_dir_transmission), + ALIGNOF(struct keep_current_dir_transmission) +}; + /******************************************************************************* * Helper functions ******************************************************************************/ @@ -255,6 +358,20 @@ setup_bsdf_transmission break; case SPHIN_BTDF_DIRECTION_KEEP_CURRENT_DIR: + res = ssf_bsdf_create + (sphor->allocator, &keep_current_dir_transmission, &bsdf); + if (RES_OK != res) { goto error; } + + res = ssf_fresnel_create + (sphor->allocator, &ssf_fresnel_constant, &fresnel); + if (RES_OK != res) { goto error; } + + res = ssf_fresnel_constant_setup(fresnel, 1 - transmissivity); + if (RES_OK != res) { goto error; } + + res = keep_current_dir_transmission_setup(bsdf, fresnel); + if (RES_OK != res) { goto error; } + break; case SPHIN_BTDF_DIRECTION_SNELL_DIELECTRIC: