commit 0861bc16a4cba9471856d02e86b71cf2679572f4
parent bac2794a8a10708c74ca758dc7ee2a4ab8cd17dc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 5 Nov 2020 09:36:32 +0100
Upd the htrdr_interface API
Add the htrdr_interface_fetch_hit_mtl function. Replace the
htrdr_interface_create_bsdf function by the htrdr_mtl_create_bsdf one
and remove the htrdr_interface_fetch_temperature function.
Diffstat:
7 files changed, 191 insertions(+), 271 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -102,7 +102,6 @@ set(HTRDR_FILES_SRC
htrdr_draw_map.c
htrdr_grid.c
htrdr_ground.c
- htrdr_interface.c
htrdr_main.c
htrdr_materials.c
htrdr_ran_wlen.c
diff --git a/src/htrdr_compute_radiance_lw.c b/src/htrdr_compute_radiance_lw.c
@@ -228,6 +228,7 @@ htrdr_compute_radiance_lw
/* Scattering at a surface */
} else {
struct htrdr_interface interf = HTRDR_INTERFACE_NULL;
+ const struct htrdr_mtl* mtl = NULL;
struct ssf_bsdf* bsdf = NULL;
double bounce_reflectivity = 0;
double N[3];
@@ -235,10 +236,10 @@ htrdr_compute_radiance_lw
ASSERT(ctx.event_type == EVENT_NONE);
ASSERT(!S3D_HIT_NONE(&s3d_hit));
- /* Fetch the hit interface and build its BSDF */
+ /* Fetch the hit interface materal and build its BSDF */
htrdr_ground_get_interface(htrdr->ground, &s3d_hit, &interf);
- HTRDR(interface_create_bsdf
- (htrdr, &interf, ithread, wlen, pos_next, dir, rng, &s3d_hit, &bsdf));
+ mtl = htrdr_interface_fetch_hit_mtl(&interf, dir, &s3d_hit);
+ HTRDR(mtl_create_bsdf(htrdr, mtl, ithread, wlen, rng, &bsdf));
d3_normalize(N, d3_set_f3(N, s3d_hit.normal));
if(d3_dot(N, wo) < 0) d3_minus(N, N);
@@ -253,25 +254,11 @@ htrdr_compute_radiance_lw
SSF(bsdf_ref_put(bsdf));
if(ssp_rng_canonical(rng) >= bounce_reflectivity) { /* Absorbed at boundary */
-#if 0
- /* Retrieve the temperature of the interface. Anyway, since we do not
- * have this data yet, we use the temperature of the sky at the current
- * position as the temperature of the surface. */
- temperature = htsky_fetch_temperature(htrdr->sky, pos_next);
-#else
- /* Retrieve the temperature of the interface. */
- temperature = htrdr_interface_fetch_temperature
- (htrdr, &interf, dir, &s3d_hit);
-#endif
- if(temperature <= 0) {
- w = 0;
- } else {
- /* weight is planck integrated over the spectral sub-interval */
- w = planck_monochromatic(wlen_m, temperature);
- }
+ temperature = mtl->temperature; /* Fetch mtl temperature */
+ /* Weight is planck integrated over the spectral sub-interval */
+ w = temperature > 0 ? planck_monochromatic(wlen_m, temperature) : 0;
break;
}
-
s3d_hit_prev = s3d_hit;
}
d3_set(pos, pos_next);
diff --git a/src/htrdr_compute_radiance_sw.c b/src/htrdr_compute_radiance_sw.c
@@ -383,11 +383,12 @@ htrdr_compute_radiance_sw
/* Sample the scattering direction */
if(surface_scattering) { /* Scattering at a surface */
struct htrdr_interface interf = HTRDR_INTERFACE_NULL;
+ const struct htrdr_mtl* mtl = NULL;
- /* Fetch the hit interface and build its BSDF */
+ /* Fetch the hit interface materal and build its BSDF */
htrdr_ground_get_interface(htrdr->ground, &s3d_hit, &interf);
- HTRDR(interface_create_bsdf
- (htrdr, &interf, ithread, wlen, pos_next, dir, rng, &s3d_hit, &bsdf));
+ mtl = htrdr_interface_fetch_hit_mtl(&interf, dir, &s3d_hit);
+ HTRDR(mtl_create_bsdf(htrdr, mtl, ithread, wlen, rng, &bsdf));
/* Revert the normal if necessary to match the SSF convention */
d3_normalize(N, d3_set_f3(N, s3d_hit.normal));
diff --git a/src/htrdr_interface.c b/src/htrdr_interface.c
@@ -1,228 +0,0 @@
-/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier
- * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "htrdr.h"
-#include "htrdr_interface.h"
-
-#include <modradurb/mrumtl.h>
-
-#include <star/s3d.h>
-#include <star/ssf.h>
-#include <star/ssp.h>
-
-#include <rsys/cstr.h>
-#include <rsys/double3.h>
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static res_T
-create_bsdf_diffuse
- (struct htrdr* htrdr,
- const struct mrumtl_brdf* brdf,
- const size_t ithread,
- struct ssf_bsdf** out_bsdf)
-{
- struct ssf_bsdf* bsdf = NULL;
- double reflectivity = 0;
- res_T res = RES_OK;
- ASSERT(htrdr && brdf && out_bsdf);
- ASSERT(mrumtl_brdf_get_type(brdf) == MRUMTL_BRDF_LAMBERTIAN);
- ASSERT(ithread < htrdr->nthreads);
-
- res = ssf_bsdf_create
- (&htrdr->lifo_allocators[ithread], &ssf_lambertian_reflection, &bsdf);
- if(res != RES_OK) goto error;
-
- reflectivity = mrumtl_brdf_lambertian_get_reflectivity(brdf);
- res = ssf_lambertian_reflection_setup(bsdf, reflectivity);
- if(res != RES_OK) goto error;
-
-exit:
- *out_bsdf = bsdf;
- return res;
-error:
- if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
- goto exit;
-}
-
-static res_T
-create_bsdf_specular
- (struct htrdr* htrdr,
- const struct mrumtl_brdf* brdf,
- const size_t ithread,
- struct ssf_bsdf** out_bsdf)
-{
- struct ssf_bsdf* bsdf = NULL;
- struct ssf_fresnel* fresnel = NULL;
- double reflectivity = 0;
- res_T res = RES_OK;
- ASSERT(htrdr && brdf && out_bsdf);
- ASSERT(mrumtl_brdf_get_type(brdf) == MRUMTL_BRDF_SPECULAR);
- ASSERT(ithread < htrdr->nthreads);
-
- res = ssf_bsdf_create
- (&htrdr->lifo_allocators[ithread], &ssf_specular_reflection, &bsdf);
- if(res != RES_OK) goto error;
-
- res = ssf_fresnel_create
- (&htrdr->lifo_allocators[ithread], &ssf_fresnel_constant, &fresnel);
- if(res != RES_OK) goto error;
-
- reflectivity = mrumtl_brdf_specular_get_reflectivity(brdf);
- res = ssf_fresnel_constant_setup(fresnel, reflectivity);
- if(res != RES_OK) goto error;
-
- res = ssf_specular_reflection_setup(bsdf, fresnel);
- if(res != RES_OK) goto error;
-
-exit:
- if(fresnel) SSF(fresnel_ref_put(fresnel));
- *out_bsdf = bsdf;
- return res;
-error:
- if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
- goto exit;
-}
-
-static const struct htrdr_mtl*
-interface_fetch_mtl
- (const struct htrdr_interface* interf,
- const double dir[3],
- struct s3d_hit* hit)
-{
- const struct htrdr_mtl* mtl = NULL;
- enum { FRONT, BACK };
- ASSERT(interf && dir && hit && !S3D_HIT_NONE(hit));
-
- if(interf->mtl_thin.mrumtl) {
- mtl = &interf->mtl_thin;
- } else {
- double N[3];
- int hit_side;
- d3_normalize(N, d3_set_f3(N, hit->normal));
- hit_side = d3_dot(N, dir) < 0 ? FRONT : BACK;
-
- /* Retrieve the brdf of the material on the other side of the hit side */
- switch(hit_side) {
- case BACK: mtl = &interf->mtl_front; break;
- case FRONT: mtl = &interf->mtl_back; break;
- default: FATAL("Unreachable code.\n"); break;
- }
-
- /* Due to numerical issue the hit side might be wrong and thus the fetched
- * material might be undefined (e.g. semi-transparent materials). Handle this
- * issue by fetching the other material. */
- if(!mtl->mrumtl) {
- switch(hit_side) {
- case BACK: mtl = &interf->mtl_back; break;
- case FRONT: mtl = &interf->mtl_front; break;
- default: FATAL("Unreachable code.\n"); break;
- }
- }
- ASSERT(mtl->mrumtl);
- }
-
- return mtl;
-}
-
-/*******************************************************************************
- * Local functions
- ******************************************************************************/
-res_T
-htrdr_interface_create_bsdf
- (struct htrdr* htrdr,
- const struct htrdr_interface* interf,
- const size_t ithread,
- const double wavelength,
- const double pos[3],
- const double dir[3],
- struct ssp_rng* rng,
- struct s3d_hit* hit,
- struct ssf_bsdf** out_bsdf)
-{
- struct ssf_bsdf* bsdf = NULL;
- const struct mrumtl_brdf* brdf = NULL;
- const struct htrdr_mtl* mtl = NULL;
- double r;
- res_T res = RES_OK;
- (void)pos;
- ASSERT(interf &&
- ( interf->mtl_front.mrumtl
- || interf->mtl_back.mrumtl
- || interf->mtl_thin.mrumtl));
- ASSERT(htrdr && interf && pos && dir && hit && out_bsdf);
- ASSERT(d3_is_normalized(dir) && !S3D_HIT_NONE(hit));
-
- mtl = interface_fetch_mtl(interf, dir, hit);
- ASSERT(mtl != NULL);
-
- r = ssp_rng_canonical(rng);
-
- res = mrumtl_fetch_brdf2(mtl->mrumtl, wavelength, r, &brdf);
- if(res != RES_OK) {
- htrdr_log_err(htrdr,
- "%s: error retrieving the MruMtl BRDF for the wavelength %g.\n",
- FUNC_NAME, wavelength);
- res = RES_BAD_ARG;
- goto error;
- }
-
- switch(mrumtl_brdf_get_type(brdf)) {
- case MRUMTL_BRDF_LAMBERTIAN:
- res = create_bsdf_diffuse(htrdr, brdf, ithread, &bsdf);
- break;
- case MRUMTL_BRDF_SPECULAR:
- res = create_bsdf_specular(htrdr, brdf, ithread, &bsdf);
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
- if(res != RES_OK) {
- htrdr_log_err(htrdr, "%s: could not create the BSDF -- %s.\n",
- FUNC_NAME, res_to_cstr(res));
- goto error;
- }
-
-exit:
- *out_bsdf = bsdf;
- return res;
-error:
- if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
- goto exit;
-}
-
-double
-htrdr_interface_fetch_temperature
- (struct htrdr* htrdr,
- const struct htrdr_interface* interf,
- const double dir[3],
- struct s3d_hit* hit)
-{
- const struct htrdr_mtl* mtl = NULL;
-
- ASSERT(interf &&
- ( interf->mtl_front.mrumtl
- || interf->mtl_back.mrumtl
- || interf->mtl_thin.mrumtl));
- ASSERT(htrdr && interf && dir && hit);
- ASSERT(d3_is_normalized(dir) && !S3D_HIT_NONE(hit));
-
- mtl = interface_fetch_mtl(interf, dir, hit);
- ASSERT(mtl != NULL);
-
- return mtl->temperature;
-}
-
diff --git a/src/htrdr_interface.h b/src/htrdr_interface.h
@@ -18,7 +18,8 @@
#define HTRDR_INTERFACE_H
#include "htrdr_materials.h"
-#include <star/ssf.h>
+#include <star/s3d.h>
+#include <rsys/double3.h>
/* Forward declaration of external data type */
struct mrumtl;
@@ -33,24 +34,49 @@ struct htrdr_interface {
};
static const struct htrdr_interface HTRDR_INTERFACE_NULL;
-extern LOCAL_SYM res_T
-htrdr_interface_create_bsdf
- (struct htrdr* htrdr,
- const struct htrdr_interface* interf,
- const size_t ithread,
- const double wavelength,
- const double pos[3],
- const double dir[3], /* Normalized incoming direction */
- struct ssp_rng* rng,
- struct s3d_hit* hit,
- struct ssf_bsdf** bsdf);
-
-extern LOCAL_SYM double
-htrdr_interface_fetch_temperature
- (struct htrdr* htrdr,
- const struct htrdr_interface* interf,
- const double dir[3], /* Normalized incoming direction */
- struct s3d_hit* hit);
+static INLINE const struct htrdr_mtl*
+htrdr_interface_fetch_hit_mtl
+ (const struct htrdr_interface* interf,
+ const double dir[3], /* Incoming ray */
+ struct s3d_hit* hit)
+{
+ const struct htrdr_mtl* mtl = NULL;
+ enum { FRONT, BACK };
+ ASSERT(interf && dir && d3_is_normalized(dir) && hit && !S3D_HIT_NONE(hit));
+ ASSERT(interf->mtl_front.mrumtl
+ || interf->mtl_back.mrumtl
+ || interf->mtl_thin.mrumtl);
+
+ if(interf->mtl_thin.mrumtl) {
+ mtl = &interf->mtl_thin;
+ } else {
+ double N[3];
+ int hit_side;
+ d3_normalize(N, d3_set_f3(N, hit->normal));
+ hit_side = d3_dot(N, dir) < 0 ? FRONT : BACK;
+
+ /* Retrieve the brdf of the material on the *other side* of the hit side */
+ switch(hit_side) {
+ case BACK: mtl = &interf->mtl_front; break;
+ case FRONT: mtl = &interf->mtl_back; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+
+ /* Due to numerical issue the hit side might be wrong and thus the fetched
+ * material might be undefined (e.g. semi-transparent materials). Handle this
+ * issue by fetching the other material. */
+ if(!mtl->mrumtl) {
+ switch(hit_side) {
+ case BACK: mtl = &interf->mtl_back; break;
+ case FRONT: mtl = &interf->mtl_front; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ }
+ ASSERT(mtl->mrumtl);
+ }
+
+ return mtl;
+}
#endif /* HTRDR_INTERFACE_H */
diff --git a/src/htrdr_materials.c b/src/htrdr_materials.c
@@ -20,8 +20,11 @@
#include "htrdr_materials.h"
#include <modradurb/mrumtl.h>
+#include <star/ssf.h>
+#include <star/ssp.h>
#include <rsys/cstr.h>
+#include <rsys/double3.h>
#include <rsys/hash_table.h>
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
@@ -240,6 +243,75 @@ materials_release(ref_T* ref)
MEM_RM(mats->htrdr->allocator, mats);
}
+static res_T
+create_bsdf_diffuse
+ (struct htrdr* htrdr,
+ const struct mrumtl_brdf* brdf,
+ const size_t ithread,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ double reflectivity = 0;
+ res_T res = RES_OK;
+ ASSERT(htrdr && brdf && out_bsdf);
+ ASSERT(mrumtl_brdf_get_type(brdf) == MRUMTL_BRDF_LAMBERTIAN);
+ ASSERT(ithread < htrdr->nthreads);
+
+ res = ssf_bsdf_create
+ (&htrdr->lifo_allocators[ithread], &ssf_lambertian_reflection, &bsdf);
+ if(res != RES_OK) goto error;
+
+ reflectivity = mrumtl_brdf_lambertian_get_reflectivity(brdf);
+ res = ssf_lambertian_reflection_setup(bsdf, reflectivity);
+ if(res != RES_OK) goto error;
+
+exit:
+ *out_bsdf = bsdf;
+ return res;
+error:
+ if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
+ goto exit;
+}
+
+static res_T
+create_bsdf_specular
+ (struct htrdr* htrdr,
+ const struct mrumtl_brdf* brdf,
+ const size_t ithread,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ struct ssf_fresnel* fresnel = NULL;
+ double reflectivity = 0;
+ res_T res = RES_OK;
+ ASSERT(htrdr && brdf && out_bsdf);
+ ASSERT(mrumtl_brdf_get_type(brdf) == MRUMTL_BRDF_SPECULAR);
+ ASSERT(ithread < htrdr->nthreads);
+
+ res = ssf_bsdf_create
+ (&htrdr->lifo_allocators[ithread], &ssf_specular_reflection, &bsdf);
+ if(res != RES_OK) goto error;
+
+ res = ssf_fresnel_create
+ (&htrdr->lifo_allocators[ithread], &ssf_fresnel_constant, &fresnel);
+ if(res != RES_OK) goto error;
+
+ reflectivity = mrumtl_brdf_specular_get_reflectivity(brdf);
+ res = ssf_fresnel_constant_setup(fresnel, reflectivity);
+ if(res != RES_OK) goto error;
+
+ res = ssf_specular_reflection_setup(bsdf, fresnel);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(fresnel) SSF(fresnel_ref_put(fresnel));
+ *out_bsdf = bsdf;
+ return res;
+error:
+ if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
+ goto exit;
+}
+
/*******************************************************************************
* Local symbol
******************************************************************************/
@@ -325,3 +397,53 @@ htrdr_materials_find_mtl
return found;
}
+res_T
+htrdr_mtl_create_bsdf
+ (struct htrdr* htrdr,
+ const struct htrdr_mtl* mtl,
+ const size_t ithread,
+ const double wavelength,
+ struct ssp_rng* rng,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ const struct mrumtl_brdf* brdf = NULL;
+ double r;
+ res_T res = RES_OK;
+ ASSERT(htrdr && mtl && wavelength && rng && out_bsdf);
+ ASSERT(ithread < htrdr->nthreads);
+
+ r = ssp_rng_canonical(rng);
+
+ res = mrumtl_fetch_brdf2(mtl->mrumtl, wavelength, r, &brdf);
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr,
+ "%s: error retrieving the MruMtl BRDF for the wavelength %g.\n",
+ FUNC_NAME, wavelength);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ switch(mrumtl_brdf_get_type(brdf)) {
+ case MRUMTL_BRDF_LAMBERTIAN:
+ res = create_bsdf_diffuse(htrdr, brdf, ithread, &bsdf);
+ break;
+ case MRUMTL_BRDF_SPECULAR:
+ res = create_bsdf_specular(htrdr, brdf, ithread, &bsdf);
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ if(res != RES_OK) {
+ htrdr_log_err(htrdr, "%s: could not create the BSDF -- %s.\n",
+ FUNC_NAME, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ *out_bsdf = bsdf;
+ return res;
+error:
+ if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; }
+ goto exit;
+}
+
diff --git a/src/htrdr_materials.h b/src/htrdr_materials.h
@@ -19,8 +19,12 @@
#include <rsys/rsys.h>
+/* Forward declarations */
struct htrdr_materials;
struct mrumtl;
+struct s3d_hit;
+struct ssf_bsdf;
+struct ssp_rng;
struct htrdr_mtl {
const char* name;
@@ -50,5 +54,14 @@ htrdr_materials_find_mtl
const char* mtl_name,
struct htrdr_mtl* mtl);
+extern LOCAL_SYM res_T
+htrdr_mtl_create_bsdf
+ (struct htrdr* htrdr,
+ const struct htrdr_mtl* mtl,
+ const size_t ithread,
+ const double wavelength,
+ struct ssp_rng* rng,
+ struct ssf_bsdf** bsdf);
+
#endif /* HTRDR_MATERIALS_H */