htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit 474640c3ae386e16da0495bad4eccd09b4ddfe21
parent f5b5aa7d0494165fd3690c24b4a8b68a07f91366
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu,  4 Oct 2018 16:02:10 +0200

Fix htrdr_compute_radiance_sw

Attach filter function to the ground geometry to avoid "self hits".

Handle the case where the ground is not a plane below the sky. In this
case, the random walk can reach a surface that does not front face the
sun. Furthermore, the sun can be occluded by a surface at any scattering
position.

Diffstat:
Msrc/htrdr.c | 22++++++++++++++++++----
Msrc/htrdr_compute_radiance_sw.c | 49+++++++++++++++++++++++++++++++++++++++++--------
Msrc/htrdr_solve.h | 9+++++++++
3 files changed, 68 insertions(+), 12 deletions(-)

diff --git a/src/htrdr.c b/src/htrdr.c @@ -164,6 +164,8 @@ setup_geometry(struct htrdr* htrdr, const char* filename) } if(filename) { + size_t ishape, nshapes; + res = s3daw_create(&htrdr->logger, htrdr->allocator, NULL, NULL, htrdr->s3d, htrdr->verbose, &s3daw); if(res != RES_OK) { @@ -175,11 +177,23 @@ setup_geometry(struct htrdr* htrdr, const char* filename) htrdr_log_err(htrdr, "could not load the obj file `%s'.\n", filename); goto error; } - res = s3daw_attach_to_scene(s3daw, scn); - if(res != RES_OK) { - htrdr_log_err(htrdr, + + S3DAW(get_shapes_count(s3daw, &nshapes)); + FOR_EACH(ishape, 0, nshapes) { + struct s3d_shape* shape; + S3DAW(get_shape(s3daw, ishape, &shape)); + res = s3d_mesh_set_hit_filter_function(shape, htrdr_ground_filter, NULL); + if(res != RES_OK) { + htrdr_log_err(htrdr, + "could not setup the hit filter function of the ground geometry.\n"); + goto error; + } + res = s3d_scene_attach_shape(scn, shape); + if(res != RES_OK) { + htrdr_log_err(htrdr, "could not attach the loaded geometry to the Star-3D scene.\n"); - goto error; + goto error; + } } } diff --git a/src/htrdr_compute_radiance_sw.c b/src/htrdr_compute_radiance_sw.c @@ -60,6 +60,21 @@ static const struct transmissivity_context TRANSMISSION_CONTEXT_NULL = { /******************************************************************************* * Helper functions ******************************************************************************/ +int +htrdr_ground_filter + (const struct s3d_hit* hit, + const float ray_org[3], + const float ray_dir[3], + void* ray_data, + void* filter_data) +{ + const struct s3d_hit* hit_prev = ray_data; + (void)ray_org, (void)ray_dir, (void)filter_data; + + if(!hit_prev) return 0; + return S3D_PRIMITIVE_EQ(&hit->prim, &hit_prev->prim); +} + static int scattering_hit_filter (const struct svx_hit* hit, @@ -308,7 +323,7 @@ htrdr_compute_radiance_sw CHK(RES_OK == ssf_phase_create (&htrdr->lifo_allocators[ithread], &ssf_phase_rayleigh, &phase_rayleigh)); - SSF(lambertian_reflection_setup(bsdf, 0.5)); + SSF(lambertian_reflection_setup(bsdf, 0.8)); /* Setup the phase function for this spectral band & quadrature point */ g = htrdr_sky_fetch_particle_phase_function_asymmetry_parameter @@ -348,6 +363,7 @@ htrdr_compute_radiance_sw /* Radiative random walk */ for(;;) { struct scattering_context scattering_ctx = SCATTERING_CONTEXT_NULL; + struct s3d_hit s3d_hit_tmp = S3D_HIT_NULL; /* Setup the ray to trace */ f3_set_d3(ray_pos, pos); @@ -395,11 +411,26 @@ htrdr_compute_radiance_sw (htrdr, rng, HTRDR_Ka, iband, iquad, pos, dir, range, &s3d_hit_prev); if(Tr_abs <= 0) break; - /* Define the transmissivity from the new position to the sun */ - d2(range, 0, FLT_MAX); + /* Sample a sun direction */ htrdr_sun_sample_direction(htrdr->sun, rng, sun_dir); - Tr = transmissivity(htrdr, rng, HTRDR_Kext, iband, iquad, pos_next, - sun_dir, range, &s3d_hit); + d2(range, 0, FLT_MAX); + + s3d_hit_prev = SVX_HIT_NONE(&svx_hit) ? s3d_hit : S3D_HIT_NULL; + + /* Check that the sun is visible from the new position */ + f3_set_d3(ray_pos, pos_next); + f3_set_d3(ray_dir, sun_dir); + f2(ray_range, 0, FLT_MAX); + S3D(scene_view_trace_ray(htrdr->s3d_scn_view, ray_pos, ray_dir, ray_range, + &s3d_hit_prev, &s3d_hit_tmp)); + + /* Define the transmissivity from the new position to the sun */ + if(!S3D_HIT_NONE(&s3d_hit_tmp)) { + Tr = 0; + } else { + Tr = transmissivity(htrdr, rng, HTRDR_Kext, iband, iquad, pos_next, + sun_dir, range, &s3d_hit_prev); + } /* Scattering at a surface */ if(SVX_HIT_NONE(&svx_hit)) { @@ -413,7 +444,11 @@ htrdr_compute_radiance_sw (bsdf, rng, wo, N, dir_next, &type, &pdf); if(ssp_rng_canonical(rng) > reflectivity) break; /* Russian roulette */ - R = ssf_bsdf_eval(bsdf, wo, N, sun_dir); + if(d3_dot(N, sun_dir) < 0) { /* Below the ground */ + R = 0; + } else { + R = ssf_bsdf_eval(bsdf, wo, N, sun_dir); + } /* Scattering in the medium */ } else { @@ -446,8 +481,6 @@ htrdr_compute_radiance_sw /* Setup the next random walk state */ d3_set(pos, pos_next); d3_set(dir, dir_next); - - s3d_hit_prev = s3d_hit; } SSF(bsdf_ref_put(bsdf)); SSF(phase_ref_put(phase_hg)); diff --git a/src/htrdr_solve.h b/src/htrdr_solve.h @@ -31,6 +31,7 @@ static const struct htrdr_accum HTRDR_ACCUM_NULL = HTRDR_ACCUM_NULL__; /* Forward declarations */ struct htrdr; struct htrdr_camera; +struct s3d_hit; struct ssp_rng; extern LOCAL_SYM double @@ -50,4 +51,12 @@ htrdr_draw_radiance_sw const size_t spp, /* #samples per pixel, i.e. #realisations */ struct htrdr_buffer* buf); /* Buffer of struct htrdr_accum[3] */ +extern LOCAL_SYM int +htrdr_ground_filter + (const struct s3d_hit* hit, + const float ray_dorg[3], + const float ray_dir[3], + void* ray_data, + void* filter_data); + #endif /* HTRDR_SOLVE_H */