solstice-solver

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

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:
Msrc/ssol.h | 13+++++++++----
Msrc/ssol_draw_pt.c | 10+++++-----
Msrc/ssol_material.c | 46++++++++++++++++++++++++----------------------
Msrc/ssol_material_c.h | 24+++++++++---------------
Msrc/ssol_solver.c | 14++++++--------
Msrc/test_ssol_material.c | 103+++++++++++++++++++++++++++++--------------------------------------------------
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); }