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:
| M | src/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: