commit 86b77d732ec84f1a8db50169d60dcc79d8786565
parent 9a8028d3fe773a138dcb3504c543385bc2363fa6
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Thu, 2 Mar 2017 10:54:26 +0100
Merge remote-tracking branch 'origin/develop' into feature_hyperbols
Diffstat:
6 files changed, 261 insertions(+), 32 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__
};
@@ -245,6 +246,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 {
@@ -585,6 +597,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);
@@ -612,6 +629,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_specular_dielectric, &bxdf);
+ if(res != RES_OK) goto error;
+ res = ssf_thin_specular_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/ssol_scene.c b/src/ssol_scene.c
@@ -428,6 +428,8 @@ hit_filter_function
/* No ray data => nothing to filter */
if(!ray_data) return 0;
+ /* Handle numerical imprecision */
+ if(hit->distance <= rdata->range_min) return 1;
/* Retrieve the intersected instance and shaded shape */
inst = *htable_instance_find(&rdata->scn->instances_rt, &hit->prim.inst_id);
@@ -458,7 +460,7 @@ hit_filter_function
/* No projection is found => the ray does not intersect the quadric */
return 1;
}
- if(dst <= rdata->range_min) {
+ if((float)dst <= rdata->range_min) {
/* Handle RT numerical imprecision, the hit is below the lower bound
* of the ray range. */
return 1;
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 */