commit e7d8ae9ccff234538fd7b8f8de1637bb95798a69
parent 0a569165b52292bd52dac89680da988386940ada
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 25 Aug 2017 16:29:01 +0200
First try at a dielectric/dielectric specular interface.
That includes both reflection and transmission.
Diffstat:
3 files changed, 156 insertions(+), 0 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -63,6 +63,7 @@ set(SSF_FILES_SRC
ssf_lambertian_reflection.c
ssf_microfacet_distribution.c
ssf_microfacet_reflection.c
+ ssf_specular_dielectric_dielectric_interface.c
ssf_specular_reflection.c
ssf_specular_transmission.c
ssf_thin_specular_dielectric.c)
diff --git a/src/ssf.h b/src/ssf.h
@@ -208,6 +208,9 @@ SSF_API const struct ssf_bxdf_type ssf_microfacet2_reflection;
* 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;
+
/* 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|
@@ -397,6 +400,12 @@ ssf_thin_specular_dielectric_setup
const double thickness); /* Thickness of the slab */
SSF_API res_T
+ssf_specular_dielectric_dielectric_interface_setup
+ (struct ssf_bxdf* bxdf,
+ 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 */
diff --git a/src/ssf_specular_dielectric_dielectric_interface.c b/src/ssf_specular_dielectric_dielectric_interface.c
@@ -0,0 +1,146 @@
+/* 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>
+#include <star/ssp.h>
+
+struct specular_dielectric_dielectric_interface {
+ struct ssf_fresnel* fresnel;
+ double eta_i; /* Refractive index of the incoming medium */
+ double eta_t; /* Refractive index of the transmissive medium */
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static res_T
+ssf_specular_dielectric_dielectric_interface_init
+ (struct mem_allocator* allocator, void* bxdf)
+{
+ struct specular_dielectric_dielectric_interface* bsdf = bxdf;
+ ASSERT(bxdf);
+ return ssf_fresnel_create
+ (allocator, &ssf_fresnel_dielectric_dielectric, &bsdf->fresnel);
+}
+
+static void
+ssf_specular_dielectric_dielectric_interface_release(void* bxdf)
+{
+ struct specular_dielectric_dielectric_interface* bsdf = bxdf;
+ SSF(fresnel_ref_put(bsdf->fresnel));
+}
+
+static double
+ssf_specular_dielectric_dielectric_interface_sample
+ (void* bxdf,
+ struct ssp_rng* rng,
+ const double wo[3],
+ const double N[3],
+ double wi[3],
+ int* type,
+ double* pdf)
+{
+ struct specular_dielectric_dielectric_interface* bsdf = bxdf;
+ 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(d3_is_normalized(wo) && d3_is_normalized(N));
+ ASSERT(d3_dot(wo, N) > -1.e-6);
+ (void)rng;
+
+ eta = bsdf->eta_i / bsdf->eta_t;
+ refracted = refract(wt, wo, N, eta);
+ if(!refracted) { /* Total reflection */
+ reflect(wi, wo, N);
+ *pdf = INF;
+ *type = SSF_SPECULAR | SSF_REFLECTION;
+ return 1;
+ }
+ fresnel = bsdf->fresnel;
+
+ cos_wo_N = MMAX(0.0, d3_dot(wo, N));
+ SSF(fresnel_dielectric_dielectric_setup(fresnel, bsdf->eta_i, bsdf->eta_t));
+ R = ssf_fresnel_eval(fresnel, cos_wo_N);
+
+ *pdf = INF;
+
+ /* Sample the output direction wrt R */
+ if(ssp_rng_canonical(rng) < R) {
+ reflect(wi, wo, N);
+ *type = SSF_SPECULAR | SSF_REFLECTION;
+ } else {
+ d3_set(wi, refracted);
+ *type = SSF_SPECULAR | SSF_TRANSMISSION;
+ }
+ return 1;
+}
+
+static double
+ssf_specular_dielectric_dielectric_interface_eval
+ (void* bxdf, const double wo[3], const double N[3], const double wi[3])
+{
+ (void)bxdf, (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)bxdf, (void)wo, (void)N, (void)wi;
+ return 0.0;
+}
+
+/*******************************************************************************
+ * Exported symbols
+ ******************************************************************************/
+const struct ssf_bxdf_type ssf_specular_dielectric_dielectric_interface = {
+ ssf_specular_dielectric_dielectric_interface_init,
+ ssf_specular_dielectric_dielectric_interface_release,
+ ssf_specular_dielectric_dielectric_interface_sample,
+ ssf_specular_dielectric_dielectric_interface_eval,
+ ssf_specular_dielectric_dielectric_interface_pdf,
+ sizeof(struct specular_dielectric_dielectric_interface),
+ ALIGNOF(struct specular_dielectric_dielectric_interface)
+};
+
+res_T
+ssf_specular_dielectric_dielectric_interface_setup
+ (struct ssf_bxdf* bxdf,
+ const double eta_i,
+ const double eta_t)
+{
+ struct specular_dielectric_dielectric_interface* bsdf;
+
+ if(!bxdf || eta_i <= 0 || eta_t <= 0)
+ return RES_BAD_ARG;
+ if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_specular_dielectric_dielectric_interface))
+ return RES_BAD_ARG;
+
+ bsdf = bxdf->data;
+
+ bsdf->eta_i = eta_i;
+ bsdf->eta_t = eta_t;
+ return RES_OK;
+}
+