commit 761a37e4e725c721ef99ea1eb44af2cb56437515
parent f8670eb2268b2604d71f04e1ea8a0664b442c28c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 22 Mar 2017 15:44:49 +0100
Add and test the dielectric material
Diffstat:
4 files changed, 147 insertions(+), 1 deletion(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -73,6 +73,7 @@ enum ssol_path_type {
};
enum ssol_material_type {
+ SSOL_MATERIAL_DIELECTRIC,
SSOL_MATERIAL_MATTE,
SSOL_MATERIAL_MIRROR,
SSOL_MATERIAL_THIN_DIELECTRIC,
@@ -238,6 +239,16 @@ typedef void
const double w[3], /* Incoming direction. Point toward the surface */
double* val); /* Returned value */
+/* Dielectric material shader */
+struct ssol_dielectric_shader {
+ ssol_shader_getter_T normal;
+ ssol_shader_getter_T eta_i; /* Refractive index of the current medium */
+ ssol_shader_getter_T eta_t; /* Refractive index of the opposite medium */
+};
+#define SSOL_DIELECTRIC_SHADER_NULL__ { NULL, NULL, NULL }
+static const struct ssol_dielectric_shader SSOL_DIELECTRIC_SHADER_NULL =
+ SSOL_DIELECTRIC_SHADER_NULL__;
+
/* Mirror material shader */
struct ssol_mirror_shader {
ssol_shader_getter_T normal;
@@ -654,6 +665,11 @@ ssol_mesh_setup
* (e.g.: refractive index) properties of a geometry.
******************************************************************************/
SSOL_API res_T
+ssol_material_create_dielectric
+ (struct ssol_device* dev,
+ struct ssol_material** mtl);
+
+SSOL_API res_T
ssol_material_create_mirror
(struct ssol_device* dev,
struct ssol_material** mtl);
@@ -692,6 +708,11 @@ ssol_material_set_param_buffer
struct ssol_param_buffer* buf);
SSOL_API res_T
+ssol_dielectric_set_shader
+ (struct ssol_material* mtl,
+ const struct ssol_dielectric_shader* shader);
+
+SSOL_API res_T
ssol_mirror_set_shader
(struct ssol_material* mtl,
const struct ssol_mirror_shader* shader);
@@ -1024,7 +1045,7 @@ SSOL_API res_T
ssol_path_get_type
(const struct ssol_path* path,
enum ssol_path_type* type);
-
+
/*******************************************************************************
* Per receiver MC estimations
******************************************************************************/
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -34,6 +34,59 @@
* Helper functions
******************************************************************************/
static res_T
+dielectric_shade
+ (const struct ssol_material* mtl,
+ const struct surface_fragment* fragment,
+ const double wavelength, /* In nanometer */
+ struct ssf_bsdf* bsdf)
+{
+ struct ssf_bxdf* brdf = NULL;
+ struct ssf_bxdf* btdf = NULL;
+ struct ssf_fresnel* fresnel = NULL;
+ const struct ssol_dielectric_shader* shader;
+ double N[3];
+ double eta_i;
+ double eta_t;
+ res_T res = RES_OK;
+ ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC);
+ ASSERT(bsdf);
+
+ shader = &mtl->data.dielectric;
+
+ /* Fetch material attribs */
+ #define FETCH(Attr, Dst) \
+ shader->Attr(mtl->dev, mtl->buf, wavelength, fragment->pos, \
+ fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, Dst)
+ FETCH(normal, N);
+ FETCH(eta_i, &eta_i);
+ FETCH(eta_t, &eta_t);
+ #undef FETCH
+
+ #define CALL(Func) { res = Func; if(res != RES_OK) goto error; } (void)0
+ /* Setup the reflective part */
+ CALL(ssf_fresnel_create
+ (mtl->dev->allocator, &ssf_fresnel_dielectric_dielectric, &fresnel));
+ CALL(ssf_fresnel_dielectric_dielectric_setup(fresnel, eta_i, eta_t));
+ CALL(ssf_bxdf_create(mtl->dev->allocator, &ssf_specular_reflection, &brdf));
+ CALL(ssf_specular_reflection_setup(brdf, fresnel));
+ /* Setup the transmissive part */
+ CALL(ssf_bxdf_create(mtl->dev->allocator, &ssf_specular_transmission, &btdf));
+ CALL(ssf_specular_transmission_setup(btdf, eta_i, eta_t));
+ /* Setup the scattering function */
+ CALL(ssf_bsdf_add(bsdf, brdf, 0.5));
+ CALL(ssf_bsdf_add(bsdf, btdf, 0.5));
+ #undef CALL
+
+exit:
+ if(brdf) SSF(bxdf_ref_put(brdf));
+ if(btdf) SSF(bxdf_ref_put(btdf));
+ if(fresnel) SSF(fresnel_ref_put(fresnel));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
matte_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
@@ -211,6 +264,9 @@ shade
/* Specific material shading */
switch(mtl->type) {
+ case SSOL_MATERIAL_DIELECTRIC:
+ res = dielectric_shade(mtl, fragment, wavelength, bsdf);
+ break;
case SSOL_MATERIAL_MATTE:
res = matte_shade(mtl, fragment, wavelength, bsdf);
break;
@@ -227,6 +283,15 @@ shade
}
static INLINE int
+check_shader_dielectric(const struct ssol_dielectric_shader* shader)
+{
+ return shader
+ && shader->normal
+ && shader->eta_i
+ && shader->eta_t;
+}
+
+static INLINE int
check_shader_mirror(const struct ssol_mirror_shader* shader)
{
return shader
@@ -349,6 +414,13 @@ ssol_material_set_param_buffer
}
res_T
+ssol_material_create_dielectric
+ (struct ssol_device* dev, struct ssol_material** out_material)
+{
+ return ssol_material_create(dev, out_material, SSOL_MATERIAL_DIELECTRIC);
+}
+
+res_T
ssol_material_create_mirror
(struct ssol_device* dev, struct ssol_material** out_material)
{
@@ -370,6 +442,18 @@ ssol_material_create_thin_dielectric
}
res_T
+ssol_dielectric_set_shader
+ (struct ssol_material* material, const struct ssol_dielectric_shader* shader)
+{
+ if(!material
+ || material->type != SSOL_MATERIAL_DIELECTRIC
+ || !check_shader_dielectric(shader))
+ return RES_BAD_ARG;
+ material->data.dielectric = *shader;
+ return RES_OK;
+}
+
+res_T
ssol_mirror_set_shader
(struct ssol_material* material, const struct ssol_mirror_shader* shader)
{
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -38,6 +38,7 @@ struct ssol_material {
enum ssol_material_type type;
union {
+ struct ssol_dielectric_shader dielectric;
struct ssol_matte_shader matte;
struct ssol_mirror_shader mirror;
struct ssol_thin_dielectric_shader thin_dielectric;
diff --git a/src/test_ssol_material.c b/src/test_ssol_material.c
@@ -151,6 +151,45 @@ test_thin_dielectric(struct ssol_device* dev)
}
static void
+test_dielectric(struct ssol_device* dev)
+{
+ struct ssol_dielectric_shader dielectric = SSOL_DIELECTRIC_SHADER_NULL;
+ struct ssol_material* material;
+ enum ssol_material_type type;
+
+ CHECK(ssol_material_create_dielectric(NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_material_create_dielectric(dev, NULL), RES_BAD_ARG);
+ CHECK(ssol_material_create_dielectric(NULL, &material), RES_BAD_ARG);
+ CHECK(ssol_material_create_dielectric(dev, &material), RES_OK);
+
+ CHECK(ssol_material_get_type(material, &type), RES_OK);
+ CHECK(type, SSOL_MATERIAL_DIELECTRIC);
+
+ dielectric.normal = get_shader_normal;
+ dielectric.eta_i = get_shader_refractive_index;
+ dielectric.eta_t = get_shader_refractive_index;
+
+ CHECK(ssol_dielectric_set_shader(NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_set_shader(material, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_set_shader(NULL, &dielectric), RES_BAD_ARG);
+ CHECK(ssol_dielectric_set_shader(material, &dielectric), RES_OK);
+
+ dielectric.normal = NULL;
+ CHECK(ssol_dielectric_set_shader(material,&dielectric), RES_BAD_ARG);
+ dielectric.normal = get_shader_normal;
+
+ dielectric.eta_i = NULL;
+ CHECK(ssol_dielectric_set_shader(material,&dielectric), RES_BAD_ARG);
+ dielectric.eta_i = get_shader_refractive_index;
+
+ dielectric.eta_t = NULL;
+ CHECK(ssol_dielectric_set_shader(material,&dielectric), RES_BAD_ARG);
+ dielectric.eta_t = get_shader_refractive_index;
+
+ CHECK(ssol_material_ref_put(material), RES_OK);
+}
+
+static void
test_virtual(struct ssol_device* dev)
{
struct ssol_material* material;
@@ -182,6 +221,7 @@ main(int argc, char** argv)
test_mirror(dev);
test_matte(dev);
test_thin_dielectric(dev);
+ test_dielectric(dev);
test_virtual(dev);
CHECK(ssol_device_ref_put(dev), RES_OK);