commit 4ea2984344dfa6da3782cb1a3de941f956e01fcc
parent e7275459ca0c03c57410e4cf23a1687b00875c05
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 27 Sep 2022 16:52:19 +0200
Add the rngrd_create_brdf function
Diffstat:
4 files changed, 187 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
@@ -15,8 +15,9 @@ on the
[RNSL](htpps://gitlab.com/meso-star/rnsl),
[RSys](https://gitlab.com/vaplv/rsys/),
[Star-3D](https://gitlab.com/meso-star/star-3d),
-[Star-Buffer](https://gitlab.com/meso-star/star-buffer), and
-[Star-Mesh](https://gitlab.com/meso-star/star-mesh)
+[Star-Buffer](https://gitlab.com/meso-star/star-buffer),
+[Star-Mesh](https://gitlab.com/meso-star/star-mesh) and
+[Star-ScatteringFunctions](https://gitlab.com/meso-star/star-sf)
libraries. It optionally depends on [scdoc](https://sr.ht/~sircmpwn/scdoc/)
which, if available, is used to generate the man pages.
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -33,8 +33,9 @@ find_package(RCMake 0.4 REQUIRED)
find_package(RNSL REQUIRED)
find_package(RSys 0.9 REQUIRED)
find_package(Star3D 0.8 REQUIRED)
-find_package(StarMesh REQUIRED)
find_package(StarBuffer REQUIRED)
+find_package(StarMesh REQUIRED)
+find_package(StarSF 0.7 REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR})
include(rcmake)
@@ -45,8 +46,9 @@ include_directories(
${RNSL_INCLUDE_DIR}
${RSys_INCLUDE_DIR}
${Star3D_INCLUDE_DIR}
+ ${StarBuffer_INCLUDE_DIR}
${StarMesh_INCLUDE_DIR}
- ${StarBuffer_INCLUDE_DIR})
+ ${StarSF_INCLUDE_DIR})
################################################################################
# Configure and define targets
@@ -74,7 +76,7 @@ rcmake_prepend_path(RNGRD_FILES_INC_API ${RNGRD_SOURCE_DIR})
rcmake_prepend_path(RNGRD_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
add_library(rngrd SHARED ${RNGRD_FILES_SRC} ${RNGRD_FILES_INC} ${RNGRD_FILES_INC_API})
-target_link_libraries(rngrd MruMtl RNSL RSys Star3D StarBuffer StarMesh)
+target_link_libraries(rngrd MruMtl RNSL RSys Star3D StarBuffer StarMesh StarSF)
if(CMAKE_COMPILER_IS_GNUCC)
target_link_libraries(rngrd m)
diff --git a/src/rngrd.h b/src/rngrd.h
@@ -46,6 +46,7 @@
/* Forward declaration of external data types */
struct logger;
struct mem_allocator;
+struct ssf_bsdf;
struct rngrd_create_args {
const char* smsh_filename; /* The Star-Mesh geometry */
@@ -94,6 +95,16 @@ struct rngrd_trace_ray_args {
static const struct rngrd_trace_ray_args RNGRD_TRACE_RAY_ARGS_DEFAULT =
RNGRD_TRACE_RAY_ARGS_DEFAULT__;
+struct rngrd_create_brdf_args {
+ struct s3d_primitive prim; /* Surfacic primitive to query */
+ double barycentric_coords[3]; /* Position into and relative to the cell */
+ double wavelength; /* In nanometers */
+ double r; /* Random number uniformly distributed in [0, 1[ */
+};
+#define RNGRD_CREATE_BRDF_ARGS_NULL__ {S3D_PRIMITIVE_NULL__, {0,0,0}, 0, 0}
+static const struct rngrd_create_brdf_args RNGRD_CREATE_BRDF_ARGS_NULL =
+ RNGRD_CREATE_BRDF_ARGS_NULL__;
+
/* Opaque data types */
struct rngrd;
@@ -129,6 +140,12 @@ rngrd_trace_ray
struct rngrd_trace_ray_args* args,
struct s3d_hit* hit);
+RNGRD_API res_T
+rngrd_create_bsdf
+ (struct rngrd* ground,
+ const struct rngrd_create_brdf_args* args,
+ struct ssf_bsdf** bsdf);
+
END_DECLS
#endif /* RNGRD_H */
diff --git a/src/rngrd_properties.c b/src/rngrd_properties.c
@@ -26,12 +26,46 @@
#include <rad-net/rnsl.h>
#include <star/sbuf.h>
+#include <star/ssf.h>
#include <rsys/cstr.h>
/*******************************************************************************
* Helper functions
******************************************************************************/
+static INLINE res_T
+check_create_brdf_args
+ (const struct rngrd* ground,
+ const struct rngrd_create_brdf_args* args)
+{
+ double sum_bcoords;
+ ASSERT(ground);
+
+ if(!args) return RES_BAD_ARG;
+
+ /* Invalid primitive */
+ if(args->prim.prim_id >= ground->ntriangles)
+ return RES_BAD_ARG;
+
+ /* Invalid barycentric_coords */
+ sum_bcoords =
+ args->barycentric_coords[0]
+ + args->barycentric_coords[1]
+ + args->barycentric_coords[2];
+ if(!eq_eps(sum_bcoords, 1, 1.e-6))
+ return RES_BAD_ARG;
+
+ /* Invalid random number */
+ if(args->r < 0 || args->r >= 1)
+ return RES_BAD_ARG;
+
+ /* Invalid wavelength */
+ if(args->wavelength < 0)
+ return RES_BAD_ARG;
+
+ return RES_OK;
+}
+
static res_T
check_sbuf_desc
(const struct rngrd* ground,
@@ -128,6 +162,134 @@ error:
goto exit;
}
+static res_T
+create_bsdf_diffuse
+ (struct rngrd* ground,
+ const struct mrumtl_brdf_lambertian* lambertian,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ struct mem_allocator* allocator = NULL;
+ res_T res = RES_OK;
+ ASSERT(ground && lambertian && out_bsdf);
+
+ /* TODO speed up allocation by using a [per thread] fifo allocator */
+ allocator = ground->allocator;
+
+ res = ssf_bsdf_create(allocator, &ssf_lambertian_reflection, &bsdf);
+ if(res != RES_OK) goto error;
+ res = ssf_lambertian_reflection_setup(bsdf, lambertian->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 rngrd* ground,
+ const struct mrumtl_brdf_specular* specular,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct ssf_bsdf* bsdf = NULL;
+ struct ssf_fresnel* fresnel = NULL;
+ struct mem_allocator* allocator = NULL;
+ res_T res = RES_OK;
+ ASSERT(ground && specular && out_bsdf);
+
+ /* TODO speed up allocation by using a [per thread] fifo allocator */
+ allocator = ground->allocator;
+
+ res = ssf_bsdf_create(allocator, &ssf_specular_reflection, &bsdf);
+ if(res != RES_OK) goto error;
+ res = ssf_fresnel_create(allocator, &ssf_fresnel_constant, &fresnel);
+ if(res != RES_OK) goto error;
+ res = ssf_fresnel_constant_setup(fresnel, specular->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;
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+rngrd_create_bsdf
+ (struct rngrd* ground,
+ const struct rngrd_create_brdf_args* args,
+ struct ssf_bsdf** out_bsdf)
+{
+ struct mrumtl_brdf_lambertian lambertian;
+ struct mrumtl_brdf_specular specular;
+ const struct ALIGN(8) { uint32_t mtl_id; float temperature; }* item = NULL;
+ const struct mrumtl_brdf* brdf = NULL;
+ const struct mrumtl* mtl = NULL;
+ struct ssf_bsdf* bsdf = NULL;
+ size_t ibrdf;
+ struct sbuf_desc desc;
+ res_T res = RES_OK;
+
+ if(!ground || !out_bsdf) { res = RES_BAD_ARG; goto error; }
+ res = check_create_brdf_args(ground, args);
+ if(res != RES_OK) goto error;
+
+ /* Retrieve the material id of the primitive to consider */
+ res = sbuf_get_desc(ground->props, &desc);
+ if(res != RES_OK) goto error;
+ item = sbuf_desc_at(&desc, args->prim.prim_id);
+
+ /* Retrieve the spectrally varying material of the primitive */
+ ASSERT(item->mtl_id < darray_mtl_size_get(&ground->mtls));
+ mtl = darray_mtl_cdata_get(&ground->mtls)[item->mtl_id];
+
+ /* Get the BRDF based on the input wavelength */
+ res = mrumtl_fetch_brdf(mtl, args->wavelength, args->r, &ibrdf);
+ if(res != RES_OK) goto error;
+ brdf = mrumtl_get_brdf(mtl, ibrdf);
+
+ /* Create the scattering function */
+ switch(mrumtl_brdf_get_type(brdf)) {
+ case MRUMTL_BRDF_LAMBERTIAN:
+ MRUMTL(brdf_get_lambertian(brdf, &lambertian));
+ res = create_bsdf_diffuse(ground, &lambertian, &bsdf);
+ if(res != RES_OK) goto error;
+ break;
+ case MRUMTL_BRDF_SPECULAR:
+ MRUMTL(brdf_get_specular(brdf, &specular));
+ res = create_bsdf_specular(ground, &specular, &bsdf);
+ if(res != RES_OK) goto error;
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+
+exit:
+ if(out_bsdf) *out_bsdf = bsdf;
+ return res;
+
+error:
+ log_err(ground, "%s: error creating the BRDF for the primitive %lu "
+ "at the wavelength %g -- %s\n",
+ FUNC_NAME, (unsigned long)args->prim.prim_id, args->wavelength,
+ res_to_cstr(res));
+ if(bsdf) {
+ SSF(bsdf_ref_put(bsdf));
+ bsdf = NULL;
+ }
+ goto exit;
+}
+
/*******************************************************************************
* Local function
******************************************************************************/