solstice-solver

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

commit 4bb38119658506de2aa1ba9f9173c3376851adc4
parent 5b1b7e0d8b475e5d19612915e158d180c68b266e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 25 Apr 2017 17:16:25 +0200

Handle spectral data in the path-tracer

Diffstat:
Msrc/ssol_draw_draft.c | 3+++
Msrc/ssol_draw_pt.c | 32++++++++++++++++++++++++--------
Msrc/ssol_scene.c | 51+++++++++++++++++++++++++++++++++++++++++++--------
Msrc/ssol_scene_c.h | 5+++++
Msrc/ssol_solver.c | 40++++------------------------------------
Msrc/ssol_sun.c | 53++++++++++++++++++++++++++++++-----------------------
Msrc/ssol_sun_c.h | 8++++++--
Msrc/test_ssol_draw.c | 20++++++++++++++++++++
Msrc/test_ssol_solver1.c | 8+++++++-
9 files changed, 142 insertions(+), 78 deletions(-)

diff --git a/src/ssol_draw_draft.c b/src/ssol_draw_draft.c @@ -157,6 +157,9 @@ ssol_draw_draft darray_float_init(scn->dev->allocator, &samples); + res = scene_check(scn, FUNC_NAME); + if(res != RES_OK) goto error; + 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 @@ -19,6 +19,7 @@ #include "ssol_draw.h" #include "ssol_material_c.h" #include "ssol_object_c.h" +#include "ssol_ranst_sun_wl.h" #include "ssol_scene_c.h" #include "ssol_shape_c.h" #include "ssol_sun_c.h" @@ -37,6 +38,7 @@ struct thread_context { struct ssp_rng* rng; struct ssf_bsdf* bsdf; + struct ranst_sun_wl* ran_wl; }; static void @@ -45,6 +47,7 @@ thread_context_release(struct thread_context* ctx) ASSERT(ctx); if(ctx->rng) SSP(rng_ref_put(ctx->rng)); if(ctx->bsdf) SSF(bsdf_ref_put(ctx->bsdf)); + if(ctx->ran_wl) ranst_sun_wl_ref_put(ctx->ran_wl); } static res_T @@ -67,12 +70,15 @@ error: static void thread_context_setup (struct thread_context* ctx, - struct ssp_rng* rng) + struct ssp_rng* rng, + struct ranst_sun_wl* ran_wl) { - ASSERT(ctx && rng); + ASSERT(ctx && rng && ran_wl); if(ctx->rng) SSP(rng_ref_put(ctx->rng)); SSP(rng_ref_get(rng)); + ranst_sun_wl_ref_get(ran_wl); ctx->rng = rng; + ctx->ran_wl = ran_wl; } /* Declare the container of the per thread contexts */ @@ -144,6 +150,7 @@ Li(struct ssol_scene* scn, double R; double pdf; double cos_wi_Ng; + double wl; const float ray_range[2] = {0, FLT_MAX}; float ray_org[3]; float ray_dir[3]; @@ -159,12 +166,14 @@ Li(struct ssol_scene* scn, f3_set(ray_org, org); f3_set(ray_dir, dir); + wl = ranst_sun_wl_get(ctx->ran_wl, ctx->rng); + for(;;) { double absorptivity; S3D(scene_view_trace_ray (view, ray_org, ray_dir, ray_range, &ray_data, &hit)); - absorptivity = ssol_data_get_value(&medium.absorptivity, 1/*Wavelength*/); + absorptivity = ssol_data_get_value(&medium.absorptivity, wl); if(absorptivity > 0) { throughput *= exp(-absorptivity * hit.distance); } @@ -206,14 +215,14 @@ Li(struct ssol_scene* scn, } surface_fragment_setup(&frag, o, wo, N, &hit.prim, hit.uv); - material_shade_normal(mtl, &frag, 1/*TODO wlen*/, N); + material_shade_normal(mtl, &frag, wl, N); /* Shaded normal may look backward the outgoing direction */ if(d3_dot(N, wo) > 0) break; SSF(bsdf_clear(ctx->bsdf)); res = material_setup_bsdf - (mtl, &frag, 1/*TODO wavelength*/, &medium, 1/*Rendering*/, ctx->bsdf); + (mtl, &frag, wl, &medium, 1/*Rendering*/, ctx->bsdf); if(res != RES_OK) goto error; /* Update the ray */ @@ -341,19 +350,25 @@ ssol_draw_pt { struct darray_thread_context thread_ctxs; struct ssp_rng_proxy* rng_proxy = NULL; + struct ranst_sun_wl* ran_sun_wl = NULL; size_t i; res_T res = RES_OK; - if(!scn) - return RES_BAD_ARG; + if(!scn) return RES_BAD_ARG; darray_thread_context_init(scn->dev->allocator, &thread_ctxs); + res = scene_check(scn, FUNC_NAME); + if(res != RES_OK) goto error; + /* Create a RNG proxy */ res = ssp_rng_proxy_create (scn->dev->allocator, &ssp_rng_threefry, scn->dev->nthreads, &rng_proxy); if(res != RES_OK) goto error; + res = sun_create_wavelength_distribution(scn->sun, &ran_sun_wl); + if(res != RES_OK) goto error; + /* Create the thread contexts */ res = darray_thread_context_resize(&thread_ctxs, scn->dev->nthreads); if(res != RES_OK) goto error; @@ -366,7 +381,7 @@ ssol_draw_pt res = ssp_rng_proxy_create_rng(rng_proxy, i, &rng); if(res != RES_OK) goto error; - thread_context_setup(ctx, rng); + thread_context_setup(ctx, rng, ran_sun_wl); SSP(rng_ref_put(rng)); } @@ -377,6 +392,7 @@ ssol_draw_pt exit: darray_thread_context_release(&thread_ctxs); if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy)); + if(ran_sun_wl) ranst_sun_wl_ref_put(ran_sun_wl); return (res_T)res; error: goto exit; diff --git a/src/ssol_scene.c b/src/ssol_scene.c @@ -14,22 +14,23 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssol.h" -#include "ssol_c.h" #include "ssol_atmosphere_c.h" -#include "ssol_scene_c.h" -#include "ssol_sun_c.h" +#include "ssol_c.h" #include "ssol_device_c.h" +#include "ssol_instance_c.h" #include "ssol_material_c.h" -#include "ssol_shape_c.h" #include "ssol_object_c.h" -#include "ssol_instance_c.h" +#include "ssol_scene_c.h" +#include "ssol_shape_c.h" +#include "ssol_spectrum_c.h" +#include "ssol_sun_c.h" +#include <rsys/double3.h> +#include <rsys/float2.h> +#include <rsys/float3.h> #include <rsys/list.h> #include <rsys/mem_allocator.h> #include <rsys/rsys.h> -#include <rsys/float2.h> -#include <rsys/float3.h> -#include <rsys/double3.h> /******************************************************************************* * Helper functions @@ -521,3 +522,37 @@ hit_filter_function return 0; } + +res_T +scene_check(const struct ssol_scene* scene, const char* caller) +{ + ASSERT(scene && caller); + + if(!scene->sun) { + log_error(scene->dev, "%s: no sun attached.\n", caller); + return RES_BAD_ARG; + } + + if(!scene->sun->spectrum) { + log_error(scene->dev, "%s: sun's spectrum undefined.\n", caller); + return RES_BAD_ARG; + } + + if(scene->sun->dni <= 0) { + log_error(scene->dev, "%s: sun's DNI undefined.\n", caller); + return RES_BAD_ARG; + } + + if(scene->atmosphere) { + int i; + ASSERT(scene->atmosphere->type == ATMOS_UNIFORM); + i = spectrum_includes + (scene->atmosphere->data.uniform.spectrum, scene->sun->spectrum); + if(!i) { + log_error(scene->dev, "%s: sun/atmosphere spectra mismatch.\n", caller); + return RES_BAD_ARG; + } + } + return RES_OK; +} + diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h @@ -60,5 +60,10 @@ scene_create_s3d_views double* sampled_area, /* Area of the instance set as "samplable" */ double* sampled_area_proxy); /* Area of the sampled geometries */ +extern LOCAL_SYM res_T +scene_check + (const struct ssol_scene* scene, + const char* caller); + #endif /* SSOL_SCENE_C_H */ diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -25,7 +25,6 @@ #include "ssol_object_c.h" #include "ssol_sun_c.h" #include "ssol_material_c.h" -#include "ssol_spectrum_c.h" #include "ssol_instance_c.h" #include "ssol_ranst_sun_dir.h" #include "ssol_ranst_sun_wl.h" @@ -485,39 +484,6 @@ point_dump /******************************************************************************* * Helper functions ******************************************************************************/ -static FINLINE res_T -check_scene(const struct ssol_scene* scene, const char* caller) -{ - ASSERT(scene && caller); - - if(!scene->sun) { - log_error(scene->dev, "%s: no sun attached.\n", caller); - return RES_BAD_ARG; - } - - if(!scene->sun->spectrum) { - log_error(scene->dev, "%s: sun's spectrum undefined.\n", caller); - return RES_BAD_ARG; - } - - if(scene->sun->dni <= 0) { - log_error(scene->dev, "%s: sun's DNI undefined.\n", caller); - return RES_BAD_ARG; - } - - if(scene->atmosphere) { - int i; - ASSERT(scene->atmosphere->type == ATMOS_UNIFORM); - i = spectrum_includes - (scene->atmosphere->data.uniform.spectrum, scene->sun->spectrum); - if(!i) { - log_error(scene->dev, "%s: sun/atmosphere spectra mismatch.\n", caller); - return RES_BAD_ARG; - } - } - return RES_OK; -} - /* Compute an empirical length of the path segment coming from/going to the * infinite, wrt the scene bounding box */ static INLINE double @@ -963,14 +929,16 @@ ssol_solve nrealisations = (int)realisations_count; nthreads = (int) scn->dev->nthreads; - res = check_scene(scn, FUNC_NAME); + res = scene_check(scn, FUNC_NAME); if(res != RES_OK) goto error; /* Create data structures shared by all threads */ res = scene_create_s3d_views(scn, &view_rt, &view_samp, &sampled_area, &sampled_area_proxy); if(res != RES_OK) goto error; - res = sun_create_distributions(scn->sun, &ran_sun_dir, &ran_sun_wl); + res = sun_create_direction_distribution(scn->sun, &ran_sun_dir); + if(res != RES_OK) goto error; + res = sun_create_wavelength_distribution(scn->sun, &ran_sun_wl); if(res != RES_OK) goto error; /* Create a RNG proxy from the submitted RNG state */ diff --git a/src/ssol_sun.c b/src/ssol_sun.c @@ -199,27 +199,13 @@ ssol_sun_set_buie_param * Local function ******************************************************************************/ res_T -sun_create_distributions - (struct ssol_sun* sun, - struct ranst_sun_dir** out_ran_dir, - struct ranst_sun_wl** out_ran_wl) +sun_create_direction_distribution + (struct ssol_sun* sun, struct ranst_sun_dir** out_ran_dir) { struct ranst_sun_dir* ran_dir = NULL; - struct ranst_sun_wl* ran_wl = NULL; res_T res = RES_OK; - ASSERT(sun && out_ran_dir && out_ran_wl); - - /* Create and setup the spectrum distribution */ - res = ranst_sun_wl_create(sun->dev->allocator, &ran_wl); - if(res != RES_OK) goto error; - - res = ranst_sun_wl_setup(ran_wl, - darray_double_cdata_get(&sun->spectrum->wavelengths), - darray_double_cdata_get(&sun->spectrum->intensities), - darray_double_size_get(&sun->spectrum->wavelengths)); - if(res != RES_OK) goto error; + ASSERT(sun && out_ran_dir); - /* Create and setup the the direction distribution */ res = ranst_sun_dir_create(sun->dev->allocator, &ran_dir); if(res != RES_OK) goto error; switch(sun->type) { @@ -236,16 +222,10 @@ sun_create_distributions break; default: FATAL("Unreachable code\n"); break; } - exit: *out_ran_dir = ran_dir; - *out_ran_wl = ran_wl; return res; error: - if(ran_wl) { - CHECK(ranst_sun_wl_ref_put(ran_wl), RES_OK); - ran_wl = NULL; - } if(ran_dir) { CHECK(ranst_sun_dir_ref_put(ran_dir), RES_OK); ran_dir = NULL; @@ -253,3 +233,30 @@ error: goto exit; } +res_T +sun_create_wavelength_distribution + (struct ssol_sun* sun, struct ranst_sun_wl** out_ran_wl) +{ + struct ranst_sun_wl* ran_wl = NULL; + res_T res = RES_OK; + ASSERT(sun && out_ran_wl); + + res = ranst_sun_wl_create(sun->dev->allocator, &ran_wl); + if(res != RES_OK) goto error; + + res = ranst_sun_wl_setup(ran_wl, + darray_double_cdata_get(&sun->spectrum->wavelengths), + darray_double_cdata_get(&sun->spectrum->intensities), + darray_double_size_get(&sun->spectrum->wavelengths)); + if(res != RES_OK) goto error; + +exit: + *out_ran_wl = ran_wl; + return res; +error: + if(ran_wl) { + CHECK(ranst_sun_wl_ref_put(ran_wl), RES_OK); + ran_wl = NULL; + } + goto exit; +} diff --git a/src/ssol_sun_c.h b/src/ssol_sun_c.h @@ -54,9 +54,13 @@ struct ssol_sun { }; extern LOCAL_SYM res_T -sun_create_distributions +sun_create_direction_distribution + (struct ssol_sun* sun, + struct ranst_sun_dir** out_ran_dir); + +extern LOCAL_SYM res_T +sun_create_wavelength_distribution (struct ssol_sun* sun, - struct ranst_sun_dir** out_ran_dir, struct ranst_sun_wl** out_ran_wl); #endif /* SSOL_SUN_C_H */ diff --git a/src/test_ssol_draw.c b/src/test_ssol_draw.c @@ -30,6 +30,17 @@ #define PITCH (WIDTH*sizeof(unsigned char[3])) #define PROJ_RATIO ((double)WIDTH/(double)HEIGHT) +static void +get_wlen(const size_t i, double* wlen, double* data, void* ctx) +{ + double wavelengths[3] = { 1, 2, 3 }; + double intensities[3] = { 1, 0.8, 1 }; + CHECK(i < 3, 1); + (void)ctx; + *wlen = wavelengths[i]; + *data = intensities[i]; +} + static res_T write_RGB8 (void* data, @@ -182,6 +193,7 @@ main(int argc, char** argv) struct ssol_device* dev; struct ssol_camera* cam; struct ssol_scene* scn; + struct ssol_spectrum* spectrum; struct ssol_sun* sun; struct image img; uint8_t* pixels; @@ -303,6 +315,13 @@ main(int argc, char** argv) CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG); CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG); CHECK(draw_func(NULL, cam, WIDTH, WIDTH, 4, write_RGB8, pixels), RES_BAD_ARG); + + /* No sun spectrum */ + CHECK(draw_func(scn, cam, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG); + + CHECK(ssol_spectrum_create(dev, &spectrum), RES_OK); + CHECK(ssol_spectrum_setup(spectrum, get_wlen, 3, NULL), RES_OK); + CHECK(ssol_sun_set_spectrum(sun, spectrum), RES_OK); CHECK(draw_func(scn, cam, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_OK); CHECK(image_write_ppm_stream(&img, 0, stdout), RES_OK); @@ -311,6 +330,7 @@ main(int argc, char** argv) CHECK(ssol_device_ref_put(dev), RES_OK); CHECK(ssol_camera_ref_put(cam), RES_OK); CHECK(ssol_scene_ref_put(scn), RES_OK); + CHECK(ssol_spectrum_ref_put(spectrum), RES_OK); CHECK(ssol_sun_ref_put(sun), RES_OK); check_memory_allocator(&allocator); diff --git a/src/test_ssol_solver1.c b/src/test_ssol_solver1.c @@ -120,7 +120,6 @@ main(int argc, char** argv) CHECK(ssol_sun_set_spectrum(sun, spectrum), RES_OK); CHECK(ssol_sun_set_dni(sun, 1000), RES_OK); CHECK(ssol_scene_create(dev, &scene), RES_OK); - CHECK(ssol_scene_attach_sun(scene, sun), RES_OK); CHECK(ssol_solve(NULL, rng, 10, 0, NULL, &estimator), RES_BAD_ARG); CHECK(ssol_solve(scene, NULL, 10, 0, NULL, &estimator), RES_BAD_ARG); @@ -164,6 +163,13 @@ main(int argc, char** argv) CHECK(ssol_instance_set_receiver(target, SSOL_FRONT, 0), RES_OK); CHECK(ssol_scene_attach_instance(scene, target), RES_OK); + /* No sun */ + CHECK(ssol_solve(scene, rng, 10, 0, NULL, &estimator), RES_BAD_ARG); + + CHECK(ssol_scene_attach_sun(scene, sun), RES_OK); + CHECK(ssol_solve(scene, rng, 10, 0, NULL, &estimator), RES_OK); + CHECK(ssol_estimator_ref_put(estimator), RES_OK); + CHECK(ssol_solve (scene, rng, 1, &SSOL_PATH_TRACKER_DEFAULT, NULL, &estimator), RES_OK);