commit 7e2dfcb9e962625fcd690b004b5583c0b00b2ff2
parent 13684364da22efe9ae2b247e148de79eb11b19fb
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 24 Mar 2017 15:19:51 +0100
Update the dielectric material API
A dielectric material is an interface between an outside & an inside
medium.
Diffstat:
6 files changed, 91 insertions(+), 119 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -227,6 +227,13 @@ struct ssol_punched_surface {
static const struct ssol_punched_surface SSOL_PUNCHED_SURFACE_NULL =
SSOL_PUNCHED_SURFACE_NULL__;
+struct ssol_medium {
+ double absorptivity;
+ double refractive_index;
+};
+#define SSOL_MEDIUM_VACUUM__ { 0, 1 }
+static const struct ssol_medium SSOL_MEDIUM_VACUUM = SSOL_MEDIUM_VACUUM__;
+
typedef void
(*ssol_shader_getter_T)
(struct ssol_device* dev,
@@ -709,10 +716,8 @@ SSOL_API res_T
ssol_dielectric_setup
(struct ssol_material* mtl,
const struct ssol_dielectric_shader* shader,
- const double eta_i, /* Refractive index of the medium the ray comes from */
- const double eta_t, /* Refractive index of the opposite medium */
- const double absorptivity_i, /* Absorptivity of the medium the ray comes from */
- const double absorptivity_t); /* Absorptivity of the opposite medium */
+ const struct ssol_medium* outside_medium,
+ const struct ssol_medium* inside_medium);
SSOL_API res_T
ssol_mirror_set_shader
diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c
@@ -129,7 +129,7 @@ Li(struct ssol_scene* scn,
const float dir[3],
double val[3])
{
- struct medium medium;
+ struct ssol_medium medium;
struct s3d_hit hit;
struct ray_data ray_data = RAY_DATA_NULL;
struct ssol_instance* inst;
@@ -160,14 +160,14 @@ Li(struct ssol_scene* scn,
f3_set(ray_dir, dir);
/* Assume that the path starts from vacuum */
- medium = vacuum;
+ medium = SSOL_MEDIUM_VACUUM;
for(;;) {
S3D(scene_view_trace_ray
(view, ray_org, ray_dir, ray_range, &ray_data, &hit));
- if(medium.absorption > 0) {
- throughput *= exp(-medium.absorption * hit.distance);
+ if(medium.absorptivity > 0) {
+ throughput *= exp(-medium.absorptivity * hit.distance);
}
if(S3D_HIT_NONE(&hit)) { /* Background lighting */
@@ -275,7 +275,7 @@ draw_pixel
double weight[3];
float samp[2]; /* Pixel sample */
float ray_org[3], ray_dir[3];
- int nfailures = 0;
+ int nfailures = 0;
/* Generate a sample into the pixel */
samp[0] = ((float)pix_coords[0]+ssp_rng_canonical_float(ctx->rng))*pix_sz[0];
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -38,7 +38,7 @@ dielectric_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- const struct medium* medium,
+ const struct ssol_medium* medium,
struct ssf_bsdf* bsdf)
{
struct ssf_bxdf* brdf = NULL;
@@ -63,8 +63,8 @@ dielectric_shade
goto error;
}
- eta_i = mtl->out_medium.eta;
- eta_t = mtl->in_medium.eta;
+ eta_i = mtl->out_medium.refractive_index;
+ eta_t = mtl->in_medium.refractive_index;
#define CALL(Func) { res = Func; if(res != RES_OK) goto error; } (void)0
/* Setup the reflective part */
@@ -261,7 +261,7 @@ shade
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
const int rendering, /* Is material used for rendering */
- const struct medium* medium,
+ const struct ssol_medium* medium,
struct ssf_bsdf* bsdf)
{
res_T res = RES_OK;
@@ -321,6 +321,14 @@ check_shader_thin_differential(const struct ssol_thin_dielectric_shader* shader)
&& shader->refractive_index;
}
+static INLINE int
+check_medium(const struct ssol_medium* medium)
+{
+ return medium
+ && medium->refractive_index > 0
+ && medium->absorptivity >= 0;
+}
+
static void
material_release(ref_T* ref)
{
@@ -362,8 +370,8 @@ ssol_material_create
material->dev = dev;
ref_init(&material->ref);
material->type = type;
- material->in_medium = vacuum;
- material->out_medium = vacuum;
+ material->in_medium = SSOL_MEDIUM_VACUUM;
+ material->out_medium = SSOL_MEDIUM_VACUUM;
exit:
if (out_material) *out_material = material;
@@ -450,24 +458,18 @@ res_T
ssol_dielectric_setup
(struct ssol_material* material,
const struct ssol_dielectric_shader* shader,
- const double eta_i,
- const double eta_t,
- const double absorption_i,
- const double absorption_t)
+ const struct ssol_medium* outside_medium,
+ const struct ssol_medium* inside_medium)
{
if(!material
|| material->type != SSOL_MATERIAL_DIELECTRIC
|| !check_shader_dielectric(shader)
- || eta_i <= 0
- || eta_t <= 0
- || absorption_i < 0
- || absorption_t < 0)
+ || !check_medium(outside_medium)
+ || !check_medium(inside_medium))
return RES_BAD_ARG;
material->data.dielectric = *shader;
- material->out_medium.eta = eta_i;
- material->out_medium.absorption = absorption_i;
- material->in_medium.eta = eta_t;
- material->in_medium.absorption = absorption_t;
+ material->out_medium = *outside_medium;
+ material->in_medium = *inside_medium;
return RES_OK;
}
@@ -592,7 +594,7 @@ material_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- const struct medium* medium,
+ const struct ssol_medium* medium,
struct ssf_bsdf* bsdf)
{
return shade(mtl, fragment, wavelength, 0, medium, bsdf);
@@ -603,7 +605,7 @@ material_shade_rendering
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- const struct medium* medium,
+ const struct ssol_medium* medium,
struct ssf_bsdf* bsdf)
{
return shade(mtl, fragment, wavelength, 1, medium, bsdf);
@@ -612,8 +614,8 @@ material_shade_rendering
res_T
material_get_next_medium
(const struct ssol_material* mtl,
- const struct medium* medium,
- struct medium* next_medium)
+ const struct ssol_medium* medium,
+ struct ssol_medium* next_medium)
{
ASSERT(mtl && medium && next_medium);
switch(mtl->type) {
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -23,15 +23,9 @@ struct s3d_primitive;
struct ssf_bsdf;
struct ssol_device;
-struct medium {
- double eta; /* Refractive index of the medium */
- double absorption;
-};
-
-static const struct medium vacuum = { 1.0, 0.0 };
-
-#define MEDIA_EQ(A, B) \
- (((A)->eta == (B)->eta) && ((A)->absorption == (B)->absorption))
+#define MEDIA_EQ(A, B) \
+ ( ((A)->refractive_index == (B)->refractive_index) \
+ && ((A)->absorptivity == (B)->absorptivity))
struct surface_fragment {
double dir[3]; /* World space incoming direction */
@@ -54,8 +48,8 @@ struct ssol_material {
struct ssol_thin_dielectric_shader thin_dielectric;
} data;
- struct medium out_medium;
- struct medium in_medium;
+ struct ssol_medium out_medium;
+ struct ssol_medium in_medium;
struct ssol_param_buffer* buf;
struct ssol_device* dev;
@@ -76,7 +70,7 @@ material_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- const struct medium* medium, /* Current medium */
+ const struct ssol_medium* medium, /* Current medium */
struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */
/* Material shading for rendering purposes */
@@ -85,13 +79,13 @@ material_shade_rendering
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- const struct medium* medium,
+ const struct ssol_medium* medium,
struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */
extern LOCAL_SYM res_T
material_get_next_medium
(const struct ssol_material* mtl,
- const struct medium* medium, /* Current mediu */
- struct medium* next_medium);
+ const struct ssol_medium* medium, /* Current mediu */
+ struct ssol_medium* next_medium);
#endif /* SSOL_MATERIAL_C_H */
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -343,7 +343,7 @@ static FINLINE res_T
point_shade
(struct point* pt,
struct ssf_bsdf* bsdf,
- struct medium* medium,
+ struct ssol_medium* medium,
struct ssp_rng* rng,
double dir[3])
{
@@ -696,7 +696,7 @@ trace_radiative_path
const struct ssol_path_tracker* tracker, /* May be NULL */
FILE* output) /* May be NULL */
{
- struct medium medium;
+ struct ssol_medium medium = SSOL_MEDIUM_VACUUM;
struct path path;
struct s3d_hit hit = S3D_HIT_NULL;
struct point pt;
@@ -713,11 +713,9 @@ trace_radiative_path
view_samp, view_rt, ran_sun_dir, ran_sun_wl, thread_ctx->rng, &is_lit);
if(res != RES_OK) goto error;
- /* Assume that the path starts from an uniform atmosphere */
- medium.eta = 1.0002772;
- medium.absorption = 0;
if(scn->atmosphere) {
- medium.absorption = atmosphere_uniform_get_absorption
+ /* Assume that the path starts from an uniform atmosphere */
+ medium.absorptivity = atmosphere_uniform_get_absorption
(scn->atmosphere, pt.wl);
}
@@ -809,8 +807,8 @@ trace_radiative_path
depth += mtl->type != SSOL_MATERIAL_VIRTUAL;
/* Take into account the medium attenuation */
- if(medium.absorption > 0 && hit.distance > 0) {
- const double transmissivity = exp(-medium.absorption * hit.distance);
+ if(medium.absorptivity > 0 && hit.distance > 0) {
+ const double transmissivity = exp(-medium.absorptivity * hit.distance);
ASSERT(0 < transmissivity && transmissivity <= 1);
pt.absorptivity_loss += (1 - transmissivity) * pt.weight;
pt.weight *= transmissivity;
diff --git a/src/test_ssol_material.c b/src/test_ssol_material.c
@@ -155,6 +155,8 @@ test_dielectric(struct ssol_device* dev)
{
struct ssol_dielectric_shader dielectric = SSOL_DIELECTRIC_SHADER_NULL;
struct ssol_material* material;
+ struct ssol_medium mdm0 = SSOL_MEDIUM_VACUUM;
+ struct ssol_medium mdm1 = SSOL_MEDIUM_VACUUM;
enum ssol_material_type type;
CHECK(ssol_material_create_dielectric(NULL, NULL), RES_BAD_ARG);
@@ -167,71 +169,42 @@ test_dielectric(struct ssol_device* dev)
dielectric.normal = get_shader_normal;
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 0, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 1, -1, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 0, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 1, 0, -1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 1, 0, -1), RES_BAD_ARG);
-
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 0, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 1, -1, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 0, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 0, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 0, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 0, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 0, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, NULL, 1, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, NULL, 1, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(NULL, &dielectric, 1, 1, 0, 1), RES_BAD_ARG);
- CHECK(ssol_dielectric_setup(material, &dielectric, 1, 1, 0, 1), RES_OK);
+ CHECK(ssol_dielectric_setup(NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, &dielectric, NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, NULL, &mdm0, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, NULL, &mdm0, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, &dielectric, &mdm0, NULL), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, NULL, NULL, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, NULL, NULL, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, NULL, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, &dielectric, NULL, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, NULL, &mdm0, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, NULL, &mdm0, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, &mdm1), RES_BAD_ARG);
+ CHECK(ssol_dielectric_setup(material, &dielectric, &mdm0, &mdm1), RES_OK);
+
+ dielectric.normal = NULL;
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, &mdm1), RES_BAD_ARG);
+ dielectric.normal = get_shader_normal;
+
+ mdm0.refractive_index = 0;
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, &mdm1), RES_BAD_ARG);
+ mdm0.refractive_index = SSOL_MEDIUM_VACUUM.refractive_index;
+
+ mdm1.refractive_index = 0;
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, &mdm1), RES_BAD_ARG);
+ mdm1.refractive_index = SSOL_MEDIUM_VACUUM.refractive_index;
+
+ mdm0.absorptivity = -1;
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, &mdm1), RES_BAD_ARG);
+ mdm0.absorptivity = SSOL_MEDIUM_VACUUM.refractive_index;
+
+ mdm1.absorptivity = -1;
+ CHECK(ssol_dielectric_setup(NULL, &dielectric, &mdm0, &mdm1), RES_BAD_ARG);
+ mdm1.refractive_index = SSOL_MEDIUM_VACUUM.refractive_index;
CHECK(ssol_material_ref_put(material), RES_OK);
}