solstice-solver

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

commit fffb2dd7c9bd659812229a1cd8667d3308ee535b
parent 897e5a1bf41fe278d83a8a6c6aed274473c66efb
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  5 Apr 2017 15:40:29 +0200

Handle normal perturbation in the "draft" rendering

Refactor how the normal perturbation is handled in the material shading.

Diffstat:
Msrc/ssol_draw_draft.c | 34++++++++++++++++++++++++++--------
Msrc/ssol_draw_pt.c | 4++--
Msrc/ssol_material.c | 126+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/ssol_material_c.h | 16++++++++--------
Msrc/ssol_solver.c | 2+-
5 files changed, 96 insertions(+), 86 deletions(-)

diff --git a/src/ssol_draw_draft.c b/src/ssol_draw_draft.c @@ -17,6 +17,7 @@ #include "ssol_camera.h" #include "ssol_device_c.h" #include "ssol_draw.h" +#include "ssol_material_c.h" #include "ssol_object_c.h" #include "ssol_scene_c.h" #include "ssol_shape_c.h" @@ -41,6 +42,7 @@ Li double val[3]) { const float range[2] = {0, FLT_MAX}; + struct surface_fragment frag; struct ray_data ray_data = RAY_DATA_NULL; struct s3d_hit hit; ASSERT(scn && view && org && dir && val); @@ -52,9 +54,11 @@ Li d3_splat(val, 0); } else { struct ssol_instance* inst; + struct ssol_material* mtl; const struct shaded_shape* sshape; size_t isshape; - float N[3]={0}; + double o[3], wi[3]; + double N[3]={0}; /* Retrieve the hit shaded shape */ inst = *htable_instance_find(&scn->instances_rt, &hit.prim.inst_id); @@ -65,12 +69,25 @@ Li /* Retrieve and normalized the hit normal */ switch(sshape->shape->type) { - case SHAPE_MESH: f3_normalize(N, hit.normal); break; - case SHAPE_PUNCHED: f3_normalize(N, f3_set_d3(N, ray_data.N)); break; + case SHAPE_MESH: d3_normalize(N, d3_set_f3(N, hit.normal)); break; + case SHAPE_PUNCHED: d3_normalize(N, ray_data.N); break; default: FATAL("Unreachable code"); break; } - ASSERT(f3_is_normalized(N)); - d3_splat(val, fabs(f3_dot(N, dir))); + + d3_set_f3(o, org); + d3_set_f3(wi, dir); + if(d3_dot(N, wi) < 0) { + mtl = sshape->mtl_front; + } else { + mtl = sshape->mtl_back; + d3_minus(N, N); + } + + surface_fragment_setup(&frag, o, wi, N, &hit.prim, hit.uv); + material_shade_normal(mtl, &frag, 1/*TODO wavelength*/, frag.Ns); + + ASSERT(d3_is_normalized(frag.Ns)); + d3_splat(val, fabs(d3_dot(frag.Ns, wi))); } } @@ -84,14 +101,14 @@ draw_pixel const float pix_sz[2], /* Normalized pixel size */ const size_t nsamples, double pixel[3], - void* ctx) + void* data) { - struct darray_float* samples = ctx; + struct darray_float* samples = data; float samp[2]; float ray_org[3], ray_dir[3]; double sum[3] = {0, 0, 0}; size_t i; - ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel && ctx); + ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel && data); (void)ithread; FOR_EACH(i, 0, nsamples) { @@ -135,6 +152,7 @@ ssol_draw_draft if(!scn || !spp) return RES_BAD_ARG; darray_float_init(scn->dev->allocator, &samples); + res = darray_float_reserve(&samples, spp * 2/*#dimensions*/); if(res != RES_OK) goto error; diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c @@ -204,8 +204,8 @@ 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); + res = material_setup_bsdf + (mtl, &frag, 1/*TODO wavelength*/, &medium, 1/*Rendering*/, ctx->bsdf); if(res != RES_OK) goto error; /* Update the ray */ diff --git a/src/ssol_material.c b/src/ssol_material.c @@ -34,7 +34,7 @@ * Helper functions ******************************************************************************/ static res_T -dielectric_shade +setup_dielectric_bsdf (const struct ssol_material* mtl, const struct surface_fragment* fragment, const double wavelength, /* In nanometer */ @@ -44,18 +44,11 @@ dielectric_shade 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]; res_T res = RES_OK; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC); ASSERT(medium && bsdf); - - shader = &mtl->data.dielectric; - - /* Fetch material attribs */ - shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos, fragment->Ng, - fragment->Ns, fragment->uv, fragment->dir, N); + (void)wavelength, (void)fragment; if(!MEDIA_EQ(medium, &mtl->out_medium)) { log_error(mtl->dev, "Inconsistent medium description.\n"); @@ -91,7 +84,7 @@ error: } static res_T -matte_shade +setup_matte_bsdf (const struct ssol_material* mtl, const struct surface_fragment* fragment, const double wavelength, /* In nanometer */ @@ -99,7 +92,6 @@ matte_shade { struct ssf_bxdf* brdf = NULL; const struct ssol_matte_shader* shader; - double normal[3]; double reflectivity; res_T res; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_MATTE); @@ -108,8 +100,6 @@ matte_shade shader = &mtl->data.matte; /* Fetch material attribs */ - shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos, - fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, normal); shader->reflectivity(mtl->dev, mtl->buf, wavelength, fragment->pos, fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, &reflectivity); @@ -131,7 +121,7 @@ error: } static res_T -mirror_shade +setup_mirror_bsdf (const struct ssol_material* mtl, const struct surface_fragment* fragment, const double wavelength, /* In nanometer */ @@ -142,7 +132,6 @@ mirror_shade struct ssf_fresnel* fresnel = NULL; struct ssf_microfacet_distribution* distrib = NULL; const struct ssol_mirror_shader* shader; - double normal[3]; double roughness; double reflectivity; res_T res; @@ -152,8 +141,6 @@ mirror_shade shader = &mtl->data.mirror; /* Fetch material attribs */ - shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos, - fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, normal); shader->reflectivity(mtl->dev, mtl->buf, wavelength, fragment->pos, fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, &reflectivity); shader->roughness(mtl->dev, mtl->buf, wavelength, fragment->pos, @@ -207,15 +194,13 @@ error: } static res_T -thin_dielectric_shade +setup_thin_dielectric_bsdf (const struct ssol_material* mtl, const struct surface_fragment* fragment, const double wavelength, /* In nanometer */ struct ssf_bsdf* bsdf) { struct ssf_bxdf* bxdf = NULL; - const struct ssol_thin_dielectric_shader* shader; - double N[3]; double thickness; double absorptivity; double eta_i; @@ -223,12 +208,8 @@ thin_dielectric_shade res_T res = RES_OK; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_THIN_DIELECTRIC); ASSERT(bsdf); + (void)wavelength, (void)fragment; - shader = &mtl->data.thin_dielectric.shader; - - /* Fetch material attribs */ - shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos, - fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, N); eta_i = mtl->out_medium.refractive_index; eta_t = mtl->data.thin_dielectric.slab_medium.refractive_index; absorptivity = mtl->data.thin_dielectric.slab_medium.absorptivity; @@ -253,39 +234,6 @@ error: goto exit; } -static INLINE res_T -shade - (const struct ssol_material* mtl, - const struct surface_fragment* fragment, - const double wavelength, /* In nanometer */ - const int rendering, /* Is material used for rendering */ - const struct ssol_medium* medium, - struct ssf_bsdf* bsdf) -{ - res_T res = RES_OK; - ASSERT(mtl); - - /* Specific material shading */ - switch(mtl->type) { - case SSOL_MATERIAL_DIELECTRIC: - res = dielectric_shade - (mtl, fragment, wavelength, medium, bsdf); - break; - case SSOL_MATERIAL_MATTE: - res = matte_shade(mtl, fragment, wavelength, bsdf); - break; - case SSOL_MATERIAL_MIRROR: - res = mirror_shade(mtl, fragment, wavelength, rendering, 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; - } - return res; -} - static INLINE int check_shader_dielectric(const struct ssol_dielectric_shader* shader) { @@ -593,28 +541,72 @@ surface_fragment_setup } } -res_T -material_shade +void +material_shade_normal (const struct ssol_material* mtl, - const struct surface_fragment* fragment, - const double wavelength, /* In nanometer */ - const struct ssol_medium* medium, - struct ssf_bsdf* bsdf) + const struct surface_fragment* frag, + const double wavelength, + double N[3]) { - return shade(mtl, fragment, wavelength, 0, medium, bsdf); + ASSERT(mtl && frag && N); + + if(mtl->type == SSOL_MATERIAL_VIRTUAL) { + d3_set(N, frag->Ns); + } else { + ssol_shader_getter_T normal; + switch(mtl->type) { + case SSOL_MATERIAL_DIELECTRIC: + normal = mtl->data.dielectric.normal; + break; + case SSOL_MATERIAL_MATTE: + normal = mtl->data.matte.normal; + break; + case SSOL_MATERIAL_MIRROR: + normal = mtl->data.mirror.normal; + break; + case SSOL_MATERIAL_THIN_DIELECTRIC: + normal = mtl->data.thin_dielectric.shader.normal; + break; + default: FATAL("Unreachable code\n"); break; + } + normal(mtl->dev, mtl->buf, wavelength, frag->pos, frag->Ng, frag->Ns, + frag->uv, frag->dir, N); + } } res_T -material_shade_rendering +material_setup_bsdf (const struct ssol_material* mtl, const struct surface_fragment* fragment, const double wavelength, /* In nanometer */ const struct ssol_medium* medium, + const int rendering, /* Is BSDF used for rendering */ struct ssf_bsdf* bsdf) { - return shade(mtl, fragment, wavelength, 1, medium, bsdf); + res_T res = RES_OK; + ASSERT(mtl); + + switch(mtl->type) { + case SSOL_MATERIAL_DIELECTRIC: + res = setup_dielectric_bsdf + (mtl, fragment, wavelength, medium, bsdf); + break; + case SSOL_MATERIAL_MATTE: + res = setup_matte_bsdf(mtl, fragment, wavelength, bsdf); + break; + case SSOL_MATERIAL_MIRROR: + res = setup_mirror_bsdf(mtl, fragment, wavelength, rendering, bsdf); + break; + case SSOL_MATERIAL_THIN_DIELECTRIC: + res = setup_thin_dielectric_bsdf(mtl, fragment, wavelength, bsdf); + break; + case SSOL_MATERIAL_VIRTUAL: /* Nothing to shade */ break; + default: FATAL("Unreachable code\n"); break; + } + return res; } + res_T material_get_next_medium (const struct ssol_material* mtl, diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h @@ -71,21 +71,20 @@ surface_fragment_setup const struct s3d_primitive* primitive, const float uv[2]); -extern LOCAL_SYM res_T -material_shade +extern LOCAL_SYM void +material_shade_normal (const struct ssol_material* mtl, const struct surface_fragment* fragment, - const double wavelength, /* In nanometer */ - const struct ssol_medium* medium, /* Current medium */ - struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */ + const double wavelength, + double N[3]); -/* Material shading for rendering purposes */ extern LOCAL_SYM res_T -material_shade_rendering +material_setup_bsdf (const struct ssol_material* mtl, const struct surface_fragment* fragment, const double wavelength, /* In nanometer */ - const struct ssol_medium* medium, + const struct ssol_medium* medium, /* Current medium */ + const int rendering, /* Is material used for rendering purposes */ struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */ extern LOCAL_SYM res_T @@ -95,3 +94,4 @@ material_get_next_medium struct ssol_medium* next_medium); #endif /* SSOL_MATERIAL_C_H */ + diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -378,7 +378,7 @@ point_shade /* Shade the surface fragment */ mtl = point_get_material(pt); SSF(bsdf_clear(bsdf)); - res = material_shade(mtl, &frag, pt->wl, medium, bsdf); + res = material_setup_bsdf(mtl, &frag, pt->wl, medium, 0, bsdf); if(res != RES_OK) return res; /* By convention, Star-SF assumes that incoming and reflected