solstice-solver

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

commit e9af5eb9633109242afbd9de53006bcecbbcc133
parent e02b19f0af176de48d9cd7885cddad9b0c89c211
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  1 Mar 2017 14:48:44 +0100

Implement and test the ssol_thin_dielectric material

Diffstat:
Msrc/ssol.h | 22++++++++++++++++++++++
Msrc/ssol_material.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/ssol_material_c.h | 1+
Msrc/test_ssol_material.c | 114++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/test_ssol_materials.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 258 insertions(+), 31 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -69,6 +69,7 @@ enum ssol_side_flag { enum ssol_material_type { SSOL_MATERIAL_MATTE, SSOL_MATERIAL_MIRROR, + SSOL_MATERIAL_THIN_DIELECTRIC, SSOL_MATERIAL_VIRTUAL, SSOL_MATERIAL_TYPES_COUNT__ }; @@ -234,6 +235,17 @@ struct ssol_matte_shader { static const struct ssol_matte_shader SSOL_MATTE_SHADER_NULL = SSOL_MATTE_SHADER_NULL__; +/* Thin dielectric shader */ +struct ssol_thin_dielectric_shader { + ssol_shader_getter_T normal; + ssol_shader_getter_T transmissivity; + ssol_shader_getter_T thickness; + ssol_shader_getter_T refractive_index; +}; +#define SSOL_THIN_DIELECTRIC_SHADER_NULL__ { NULL, NULL, NULL, NULL } +static const struct ssol_thin_dielectric_shader +SSOL_THIN_DIELECTRIC_SHADER_NULL = SSOL_THIN_DIELECTRIC_SHADER_NULL__; + /* The type of data produced on receiver hits as ssol_solve() write them on its * FILE* argument */ struct ssol_receiver_data { @@ -574,6 +586,11 @@ ssol_material_create_virtual struct ssol_material** mtl); SSOL_API res_T +ssol_material_create_thin_dielectric + (struct ssol_device* dev, + struct ssol_material** mtl); + +SSOL_API res_T ssol_material_get_type (const struct ssol_material* mtl, enum ssol_material_type* type); @@ -601,6 +618,11 @@ ssol_matte_set_shader (struct ssol_material* mtl, const struct ssol_matte_shader* shader); +SSOL_API res_T +ssol_thin_dielectric_set_shader + (struct ssol_material* mtl, + const struct ssol_thin_dielectric_shader* shader); + /******************************************************************************* * Object API - Opaque abstraction of a geometry with its associated properties. ******************************************************************************/ diff --git a/src/ssol_material.c b/src/ssol_material.c @@ -140,17 +140,52 @@ error: goto exit; } -static void -material_release(ref_T* ref) +static res_T +thin_dielectric_shade + (const struct ssol_material* mtl, + const struct surface_fragment* fragment, + const double wavelength, /* In nanometer */ + struct ssf_bsdf* bsdf) { - struct ssol_device* dev; - struct ssol_material* material = CONTAINER_OF(ref, struct ssol_material, ref); - ASSERT(ref); - dev = material->dev; - if(material->buf) SSOL(param_buffer_ref_put(material->buf)); - ASSERT(dev && dev->allocator); - MEM_RM(dev->allocator, material); - SSOL(device_ref_put(dev)); + struct ssf_bxdf* bxdf = NULL; + const struct ssol_thin_dielectric_shader* shader; + double N[3]; + double thickness; + double T; + const double eta_i = 1.0002772; /* Refractive index of the air */ + double eta_t; + res_T res = RES_OK; + ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_THIN_DIELECTRIC); + ASSERT(bsdf); + + shader = &mtl->data.thin_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(thickness, &thickness); + FETCH(transmissivity, &T); + FETCH(refractive_index, &eta_t); + #undef FETCH + + /* Setup the BxDF */ + res = ssf_bxdf_create + (mtl->dev->allocator, &ssf_thin_transparent_dielectric, &bxdf); + if(res != RES_OK) goto error; + res = ssf_thin_transparent_dielectric_setup(bxdf, T, eta_i, eta_t, thickness); + if(res != RES_OK) goto error; + + /* Setup the BSDF */ + res = ssf_bsdf_add(bsdf, bxdf, 1.0); + if(res != RES_OK) goto error; + +exit: + if(bxdf) SSF(bxdf_ref_put(bxdf)); + return res; +error: + goto exit; } static INLINE int @@ -170,6 +205,29 @@ check_shader_matte(const struct ssol_matte_shader* shader) && shader->reflectivity; } +static INLINE int +check_shader_thin_differential(const struct ssol_thin_dielectric_shader* shader) +{ + return shader + && shader->normal + && shader->transmissivity + && shader->thickness + && shader->refractive_index; +} + +static void +material_release(ref_T* ref) +{ + struct ssol_device* dev; + struct ssol_material* material = CONTAINER_OF(ref, struct ssol_material, ref); + ASSERT(ref); + dev = material->dev; + if(material->buf) SSOL(param_buffer_ref_put(material->buf)); + ASSERT(dev && dev->allocator); + MEM_RM(dev->allocator, material); + SSOL(device_ref_put(dev)); +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -267,6 +325,13 @@ ssol_material_create_matte } res_T +ssol_material_create_thin_dielectric + (struct ssol_device* dev, struct ssol_material** out_material) +{ + return ssol_material_create(dev, out_material, SSOL_MATERIAL_THIN_DIELECTRIC); +} + +res_T ssol_mirror_set_shader (struct ssol_material* material, const struct ssol_mirror_shader* shader) { @@ -291,6 +356,19 @@ ssol_matte_set_shader } res_T +ssol_thin_dielectric_set_shader + (struct ssol_material* material, + const struct ssol_thin_dielectric_shader* shader) +{ + if(!material + || material->type != SSOL_MATERIAL_THIN_DIELECTRIC + || !check_shader_thin_differential(shader)) + return RES_BAD_ARG; + material->data.thin_dielectric = *shader; + return RES_OK; +} + +res_T ssol_material_create_virtual (struct ssol_device* dev, struct ssol_material** out_material) { @@ -387,6 +465,9 @@ material_shade case SSOL_MATERIAL_MIRROR: res = mirror_shade(mtl, fragment, wavelength, bsdf); break; + case SSOL_MATERIAL_THIN_DIELECTRIC: + res = thin_dielectric_shade(mtl, fragment, wavelength, bsdf); + break; case SSOL_MATERIAL_VIRTUAL: /* Nothing to shade */ break; default: FATAL("Unreachable code\n"); break; } diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h @@ -40,6 +40,7 @@ struct ssol_material { union { struct ssol_matte_shader matte; struct ssol_mirror_shader mirror; + struct ssol_thin_dielectric_shader thin_dielectric; } data; struct ssol_param_buffer* buf; diff --git a/src/test_ssol_material.c b/src/test_ssol_material.c @@ -17,23 +17,15 @@ #include "test_ssol_utils.h" #include "test_ssol_materials.h" -int -main(int argc, char** argv) +static void +test_mirror(struct ssol_device* dev) { - struct mem_allocator allocator; - struct ssol_device* dev; - struct ssol_material* material; struct ssol_mirror_shader mirror = SSOL_MIRROR_SHADER_NULL; - struct ssol_matte_shader matte = SSOL_MATTE_SHADER_NULL; struct ssol_param_buffer* pbuf = NULL; + struct ssol_material* material; enum ssol_material_type type; - (void) argc, (void) argv; - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - - CHECK(ssol_device_create - (NULL, &allocator, SSOL_NTHREADS_DEFAULT, 0, &dev), RES_OK); + CHECK(ssol_material_create_mirror(NULL, NULL), RES_BAD_ARG); CHECK(ssol_material_create_mirror(NULL, &material), RES_BAD_ARG); CHECK(ssol_material_create_mirror(dev, NULL), RES_BAD_ARG); CHECK(ssol_material_create_mirror(dev, &material), RES_OK); @@ -79,16 +71,15 @@ main(int argc, char** argv) mirror.roughness = get_shader_roughness; CHECK(ssol_material_ref_put(material), RES_OK); - - CHECK(ssol_material_create_virtual(NULL, &material), RES_BAD_ARG); - CHECK(ssol_material_create_virtual(dev, NULL), RES_BAD_ARG); - CHECK(ssol_material_create_virtual(dev, &material), RES_OK); - - CHECK(ssol_material_get_type(material, &type), RES_OK); - CHECK(type, SSOL_MATERIAL_VIRTUAL); - - CHECK(ssol_material_ref_put(material), RES_OK); CHECK(ssol_param_buffer_ref_put(pbuf), RES_OK); +} + +static void +test_matte(struct ssol_device* dev) +{ + struct ssol_matte_shader matte = SSOL_MATTE_SHADER_NULL; + struct ssol_material* material; + enum ssol_material_type type; CHECK(ssol_material_create_matte(NULL, NULL), RES_BAD_ARG); CHECK(ssol_material_create_matte(dev, NULL), RES_BAD_ARG); @@ -112,6 +103,87 @@ main(int argc, char** argv) CHECK(ssol_matte_set_shader(material, &matte), RES_BAD_ARG); CHECK(ssol_material_ref_put(material), RES_OK); +} + +static void +test_thin_dielectric(struct ssol_device* dev) +{ + struct ssol_thin_dielectric_shader thin_dielectric = + SSOL_THIN_DIELECTRIC_SHADER_NULL; + struct ssol_material* material; + enum ssol_material_type type; + + CHECK(ssol_material_create_thin_dielectric(NULL, NULL), RES_BAD_ARG); + CHECK(ssol_material_create_thin_dielectric(dev, NULL), RES_BAD_ARG); + CHECK(ssol_material_create_thin_dielectric(NULL, &material), RES_BAD_ARG); + CHECK(ssol_material_create_thin_dielectric(dev, &material), RES_OK); + + CHECK(ssol_material_get_type(material, &type), RES_OK); + CHECK(type, SSOL_MATERIAL_THIN_DIELECTRIC); + + thin_dielectric.normal = get_shader_normal; + thin_dielectric.transmissivity = get_shader_transmissivity; + thin_dielectric.thickness = get_shader_thickness; + thin_dielectric.refractive_index = get_shader_refractive_index; + + CHECK(ssol_thin_dielectric_set_shader(NULL, NULL), RES_BAD_ARG); + CHECK(ssol_thin_dielectric_set_shader(material, NULL), RES_BAD_ARG); + CHECK(ssol_thin_dielectric_set_shader(NULL, &thin_dielectric), RES_BAD_ARG); + CHECK(ssol_thin_dielectric_set_shader(material, &thin_dielectric), RES_OK); + + thin_dielectric.normal = NULL; + CHECK(ssol_thin_dielectric_set_shader(material, &thin_dielectric), RES_BAD_ARG); + thin_dielectric.normal = get_shader_normal; + + thin_dielectric.transmissivity = NULL; + CHECK(ssol_thin_dielectric_set_shader(material, &thin_dielectric), RES_BAD_ARG); + thin_dielectric.transmissivity = get_shader_transmissivity; + + thin_dielectric.thickness = NULL; + CHECK(ssol_thin_dielectric_set_shader(material, &thin_dielectric), RES_BAD_ARG); + thin_dielectric.thickness = get_shader_thickness; + + thin_dielectric.refractive_index = NULL; + CHECK(ssol_thin_dielectric_set_shader(material, &thin_dielectric), RES_BAD_ARG); + thin_dielectric.thickness = get_shader_refractive_index; + + CHECK(ssol_material_ref_put(material), RES_OK); +} + +static void +test_virtual(struct ssol_device* dev) +{ + struct ssol_material* material; + enum ssol_material_type type; + + CHECK(ssol_material_create_virtual(NULL, NULL), RES_BAD_ARG); + CHECK(ssol_material_create_virtual(NULL, &material), RES_BAD_ARG); + CHECK(ssol_material_create_virtual(dev, NULL), RES_BAD_ARG); + CHECK(ssol_material_create_virtual(dev, &material), RES_OK); + + CHECK(ssol_material_get_type(material, &type), RES_OK); + CHECK(type, SSOL_MATERIAL_VIRTUAL); + + CHECK(ssol_material_ref_put(material), RES_OK); +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct ssol_device* dev; + (void) argc, (void) argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + CHECK(ssol_device_create + (NULL, &allocator, SSOL_NTHREADS_DEFAULT, 0, &dev), RES_OK); + + test_mirror(dev); + test_matte(dev); + test_thin_dielectric(dev); + test_virtual(dev); + CHECK(ssol_device_ref_put(dev), RES_OK); check_memory_allocator(&allocator); diff --git a/src/test_ssol_materials.h b/src/test_ssol_materials.h @@ -90,4 +90,55 @@ get_shader_roughness *val = 0; } +static INLINE void +get_shader_transmissivity + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const double P[3], + const double Ng[3], + const double Ns[3], + const double uv[2], + const double w[3], + double* val) +{ + (void)dev, (void)buf, (void)wavelength; + (void)P, (void)Ng, (void)Ns, (void)uv, (void) w; + *val = 1; +} + +static INLINE void +get_shader_thickness + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const double P[3], + const double Ng[3], + const double Ns[3], + const double uv[2], + const double w[3], + double* val) +{ + (void)dev, (void)buf, (void)wavelength; + (void)P, (void)Ng, (void)Ns, (void)uv, (void) w; + *val = 1; +} + +static INLINE void +get_shader_refractive_index + (struct ssol_device* dev, + struct ssol_param_buffer* buf, + const double wavelength, + const double P[3], + const double Ng[3], + const double Ns[3], + const double uv[2], + const double w[3], + double* val) +{ + (void)dev, (void)buf, (void)wavelength; + (void)P, (void)Ng, (void)Ns, (void)uv, (void) w; + *val = 1.5; +} + #endif /* TEST_SSOL_MATERIALS_H */