rngrd

Describe a surface and its physical properties
git clone git://git.meso-star.fr/rngrd.git
Log | Files | Refs | README | LICENSE

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:
MREADME.md | 5+++--
Mcmake/CMakeLists.txt | 8+++++---
Msrc/rngrd.h | 17+++++++++++++++++
Msrc/rngrd_properties.c | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 ******************************************************************************/