solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

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:
Msrc/ssol.h | 23++++++++++++++++++++++-
Msrc/ssol_material.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ssol_material_c.h | 1+
Msrc/test_ssol_material.c | 40++++++++++++++++++++++++++++++++++++++++
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);