commit 13684364da22efe9ae2b247e148de79eb11b19fb
parent afb9005008dc351bd03b750adfb5201ff1311307
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 24 Mar 2017 14:51:03 +0100
Major refactoring of the dielectric material
The refractive index and the absorptivity are no more retrieved by the
shader but are constant for the whole material.
Diffstat:
6 files changed, 191 insertions(+), 77 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -242,11 +242,8 @@ typedef void
/* 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 */
- ssol_shader_getter_T absorption; /* Medium absorption */
};
-#define SSOL_DIELECTRIC_SHADER_NULL__ { NULL, NULL, NULL, NULL }
+#define SSOL_DIELECTRIC_SHADER_NULL__ { NULL }
static const struct ssol_dielectric_shader SSOL_DIELECTRIC_SHADER_NULL =
SSOL_DIELECTRIC_SHADER_NULL__;
@@ -709,9 +706,13 @@ ssol_material_set_param_buffer
struct ssol_param_buffer* buf);
SSOL_API res_T
-ssol_dielectric_set_shader
+ssol_dielectric_setup
(struct ssol_material* mtl,
- const struct ssol_dielectric_shader* shader);
+ 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 */
SSOL_API res_T
ssol_mirror_set_shader
diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c
@@ -121,7 +121,7 @@ sun_lighting
return 0;
}
-static void
+static res_T
Li(struct ssol_scene* scn,
struct thread_context* ctx,
struct s3d_scene_view* view,
@@ -149,6 +149,7 @@ Li(struct ssol_scene* scn,
float ray_dir[3];
enum ssol_side_flag side;
int russian_roulette = 0;
+ int type;
res_T res = RES_OK;
ASSERT(scn && view && org && dir && val);
@@ -158,9 +159,8 @@ Li(struct ssol_scene* scn,
f3_set(ray_org, org);
f3_set(ray_dir, dir);
- /* Assume that the path starts from the air */
- medium.eta = 1.00027;
- medium.absorption = 0;
+ /* Assume that the path starts from vacuum */
+ medium = vacuum;
for(;;) {
S3D(scene_view_trace_ray
@@ -204,8 +204,9 @@ Li(struct ssol_scene* scn,
surface_fragment_setup(&frag, o, wo, N, &hit.prim, hit.uv);
SSF(bsdf_clear(ctx->bsdf));
- res = material_shade_rendering(mtl, &frag, 1/*TODO wavelength*/, &medium, ctx->bsdf);
- CHECK(res, RES_OK);
+ res = material_shade_rendering
+ (mtl, &frag, 1/*TODO wavelength*/, &medium, ctx->bsdf);
+ if(res != RES_OK) goto error;
/* Update the ray */
ray_data.prim_from = hit.prim;
@@ -220,9 +221,10 @@ Li(struct ssol_scene* scn,
(scn->sun, view, &ray_data, ctx->bsdf, wo, N, ray_org);
}
- R = ssf_bsdf_sample(ctx->bsdf, ctx->rng, wo, frag.Ns, wi, &pdf);
+ R = ssf_bsdf_sample(ctx->bsdf, ctx->rng, wo, frag.Ns, wi, &type, &pdf);
ASSERT(0 <= R && R <= 1);
f3_set_d3(ray_dir, wi);
+ if(type & SSF_TRANSMISSION) material_get_next_medium(mtl, &medium, &medium);
if(!russian_roulette) {
throughput *= fabs(d3_dot(wi, N)) * R;
@@ -238,6 +240,12 @@ Li(struct ssol_scene* scn,
}
}
d3_splat(val, L);
+
+exit:
+ return res;
+error:
+ d3(val, 1, 1, 0);
+ goto exit;
}
static void
@@ -256,30 +264,43 @@ draw_pixel
struct thread_context* ctx;
double sum[3] = {0, 0, 0};
size_t isample;
+ res_T res = RES_OK;
ASSERT(scn && cam && pix_coords && pix_sz && nsamples && pixel && data);
ASSERT((size_t)ithread < darray_thread_context_size_get(thread_ctxs));
ctx = darray_thread_context_data_get(thread_ctxs) + ithread;
FOR_EACH(isample, 0, nsamples) {
+ const int MAX_NFAILURES = 10;
double weight[3];
float samp[2]; /* Pixel sample */
float ray_org[3], ray_dir[3];
+ int nfailures = 0;
/* Generate a sample into the pixel */
samp[0] = ((float)pix_coords[0]+ssp_rng_canonical_float(ctx->rng))*pix_sz[0];
samp[1] = ((float)pix_coords[1]+ssp_rng_canonical_float(ctx->rng))*pix_sz[1];
- /* Generate a ray starting from the pinhole camera and passing through the
- * pixel sample */
- camera_ray(cam, samp, ray_org, ray_dir);
+ do {
+ /* Generate a ray starting from the pinhole camera and passing through the
+ * pixel sample */
+ camera_ray(cam, samp, ray_org, ray_dir);
+
+ /* Compute the radiance arriving through the sampled camera ray */
+ res = Li(scn, ctx, view, ray_org, ray_dir, weight);
+ } while(res == RES_BAD_OP && ++nfailures < MAX_NFAILURES);
+ if(res != RES_OK) goto error;
- /* Compute the radiance arriving through the sampled camera ray */
- Li(scn, ctx, view, ray_org, ray_dir, weight);
d3_add(sum, sum, weight);
}
d3_divd(pixel, sum, (double)nsamples);
+exit:
+ return;
+error:
+ log_error(scn->dev, "Path tracing integrator error.\n");
+ d3(pixel, 1, 1, 0);
+ goto exit;
}
/*******************************************************************************
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -38,39 +38,34 @@ dielectric_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct medium* medium,
+ const struct medium* medium,
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 eta_i, eta_t;
double N[3];
- double eta_i;
- double eta_t;
- double absorption;
res_T res = RES_OK;
- ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC && medium);
- ASSERT(bsdf);
+ ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC);
+ ASSERT(medium && 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);
- FETCH(absorption, &absorption);
- #undef FETCH
+ shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos, fragment->Ng,
+ fragment->Ns, fragment->uv, fragment->dir, N);
- if(!eq_eps(medium->eta, eta_i, 1.e-3)) {
- log_error(mtl->dev, "Inconsistent medium definition.\n");
- res = RES_BAD_ARG;
+ if(!MEDIA_EQ(medium, &mtl->out_medium)) {
+ log_error(mtl->dev, "Inconsistent medium description.\n");
+ res = RES_BAD_OP;
goto error;
}
+ eta_i = mtl->out_medium.eta;
+ eta_t = mtl->in_medium.eta;
+
#define CALL(Func) { res = Func; if(res != RES_OK) goto error; } (void)0
/* Setup the reflective part */
CALL(ssf_fresnel_create
@@ -86,9 +81,6 @@ dielectric_shade
CALL(ssf_bsdf_add(bsdf, btdf, 0.5));
#undef CALL
- medium->absorption = absorption;
- medium->eta = eta_t;
-
exit:
if(brdf) SSF(bxdf_ref_put(brdf));
if(btdf) SSF(bxdf_ref_put(btdf));
@@ -269,7 +261,7 @@ shade
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
const int rendering, /* Is material used for rendering */
- struct medium* medium,
+ const struct medium* medium,
struct ssf_bsdf* bsdf)
{
res_T res = RES_OK;
@@ -278,7 +270,8 @@ shade
/* Specific material shading */
switch(mtl->type) {
case SSOL_MATERIAL_DIELECTRIC:
- res = dielectric_shade(mtl, fragment, wavelength, medium, bsdf);
+ res = dielectric_shade
+ (mtl, fragment, wavelength, medium, bsdf);
break;
case SSOL_MATERIAL_MATTE:
res = matte_shade(mtl, fragment, wavelength, bsdf);
@@ -298,11 +291,7 @@ shade
static INLINE int
check_shader_dielectric(const struct ssol_dielectric_shader* shader)
{
- return shader
- && shader->normal
- && shader->eta_i
- && shader->eta_t
- && shader->absorption;
+ return shader && shader->normal;
}
static INLINE int
@@ -373,6 +362,8 @@ ssol_material_create
material->dev = dev;
ref_init(&material->ref);
material->type = type;
+ material->in_medium = vacuum;
+ material->out_medium = vacuum;
exit:
if (out_material) *out_material = material;
@@ -456,14 +447,27 @@ ssol_material_create_thin_dielectric
}
res_T
-ssol_dielectric_set_shader
- (struct ssol_material* material, const struct ssol_dielectric_shader* shader)
+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)
{
if(!material
|| material->type != SSOL_MATERIAL_DIELECTRIC
- || !check_shader_dielectric(shader))
+ || !check_shader_dielectric(shader)
+ || eta_i <= 0
+ || eta_t <= 0
+ || absorption_i < 0
+ || absorption_t < 0)
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;
return RES_OK;
}
@@ -588,7 +592,7 @@ material_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct medium* medium,
+ const struct medium* medium,
struct ssf_bsdf* bsdf)
{
return shade(mtl, fragment, wavelength, 0, medium, bsdf);
@@ -599,9 +603,36 @@ material_shade_rendering
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct medium* medium,
+ const struct medium* medium,
struct ssf_bsdf* bsdf)
{
return shade(mtl, fragment, wavelength, 1, medium, bsdf);
}
+res_T
+material_get_next_medium
+ (const struct ssol_material* mtl,
+ const struct medium* medium,
+ struct medium* next_medium)
+{
+ ASSERT(mtl && medium && next_medium);
+ switch(mtl->type) {
+ /* The material is an interface between 2 media */
+ case SSOL_MATERIAL_DIELECTRIC:
+ if(MEDIA_EQ(&mtl->out_medium, medium)) {
+ *next_medium = mtl->in_medium;
+ } else {
+ *next_medium = mtl->out_medium;
+ }
+ break;
+ /* The material is not an interface between 2 media */
+ case SSOL_MATERIAL_MATTE:
+ case SSOL_MATERIAL_MIRROR:
+ case SSOL_MATERIAL_THIN_DIELECTRIC:
+ *next_medium = *medium;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ return RES_OK;
+}
+
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -28,6 +28,11 @@ struct 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))
+
struct surface_fragment {
double dir[3]; /* World space incoming direction */
double pos[3]; /* World space position */
@@ -49,6 +54,9 @@ struct ssol_material {
struct ssol_thin_dielectric_shader thin_dielectric;
} data;
+ struct medium out_medium;
+ struct medium in_medium;
+
struct ssol_param_buffer* buf;
struct ssol_device* dev;
ref_T ref;
@@ -68,7 +76,7 @@ material_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct medium* medium,
+ const struct medium* medium, /* Current medium */
struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */
/* Material shading for rendering purposes */
@@ -77,7 +85,13 @@ material_shade_rendering
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct medium* medium,
+ const struct 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);
+
#endif /* SSOL_MATERIAL_C_H */
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -347,10 +347,13 @@ point_shade
struct ssp_rng* rng,
double dir[3])
{
+ struct ssol_material* mtl;
struct surface_fragment frag;
double reflectivity = 1;
double wi[3], pdf;
+ int type;
res_T res;
+ ASSERT(pt && bsdf && medium && rng && dir);
/* TODO ensure that if `prim' was sampled, then the surface fragment setup
* remains valid in *all* situations, i.e. even though the point primitive
@@ -366,19 +369,21 @@ point_shade
surface_fragment_setup(&frag, pt->pos, pt->dir, pt->N, &pt->prim, pt->uv);
/* Shade the surface fragment */
+ mtl = point_get_material(pt);
SSF(bsdf_clear(bsdf));
- res = material_shade(point_get_material(pt), &frag, pt->wl, medium, bsdf);
+ res = material_shade(mtl, &frag, pt->wl, medium, bsdf);
if(res != RES_OK) return res;
/* By convention, Star-SF assumes that incoming and reflected
* directions point outward the surface => negate incoming dir */
d3_minus(wi, pt->dir);
- reflectivity = ssf_bsdf_sample(bsdf, rng, wi, frag.Ns, dir, &pdf);
+ reflectivity = ssf_bsdf_sample(bsdf, rng, wi, frag.Ns, dir, &type, &pdf);
ASSERT(0 <= reflectivity && reflectivity <= 1);
pt->reflectivity_loss += (1 - reflectivity) * pt->weight;
pt->weight *= reflectivity;
+ if(type & SSF_TRANSMISSION) material_get_next_medium(mtl, medium, medium);
return RES_OK;
}
diff --git a/src/test_ssol_material.c b/src/test_ssol_material.c
@@ -166,30 +166,72 @@ test_dielectric(struct ssol_device* dev)
CHECK(type, SSOL_MATERIAL_DIELECTRIC);
dielectric.normal = get_shader_normal;
- dielectric.eta_i = get_shader_refractive_index;
- dielectric.eta_t = get_shader_refractive_index;
- dielectric.absorption = get_shader_absorption;
- 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;
-
- dielectric.absorption = NULL;
- CHECK(ssol_dielectric_set_shader(material, &dielectric), RES_BAD_ARG);
- dielectric.absorption = get_shader_absorption;
+ 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_material_ref_put(material), RES_OK);
}