commit 233b99fa91f1ecaf6ee6748ad9462064663a1083
parent 8ce2024b7c880c7e55353f173e3d56b911c98797
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 14 Dec 2016 16:58:03 +0100
Add and test the matte material
Diffstat:
4 files changed, 135 insertions(+), 28 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -199,7 +199,7 @@ typedef void
const double w[3], /* Incoming direction. Point toward the surface */
double* val); /* Returned value */
-/* Material descriptors */
+/* Mirror material shader */
struct ssol_mirror_shader {
ssol_shader_getter_T normal;
ssol_shader_getter_T reflectivity;
@@ -209,6 +209,15 @@ struct ssol_mirror_shader {
static const struct ssol_mirror_shader SSOL_MIRROR_SHADER_NULL =
SSOL_MIRROR_SHADER_NULL__;
+/* Matte material shader */
+struct ssol_matte_shader {
+ ssol_shader_getter_T normal;
+ ssol_shader_getter_T reflectivity;
+};
+#define SSOL_MATTE_SHADER_NULL__ { NULL, NULL }
+static const struct ssol_matte_shader SSOL_MATTE_SHADER_NULL =
+ SSOL_MATTE_SHADER_NULL__;
+
/* The type of data produced on receiver hits as ssol_solve() write them on its
* FILE* argument */
struct ssol_receiver_data {
@@ -480,6 +489,11 @@ ssol_material_create_mirror
struct ssol_material** mtl);
SSOL_API res_T
+ssol_material_create_matte
+ (struct ssol_device* dev,
+ struct ssol_material** mtl);
+
+SSOL_API res_T
ssol_material_create_virtual
(struct ssol_device* dev,
struct ssol_material** mtl);
@@ -502,6 +516,11 @@ ssol_mirror_set_shader
(struct ssol_material* mtl,
const struct ssol_mirror_shader* shader);
+SSOL_API res_T
+ssol_matte_set_shader
+ (struct ssol_material* mtl,
+ const struct ssol_matte_shader* shader);
+
/*******************************************************************************
* Object API - Opaque abstraction of a geometry with its associated properties.
******************************************************************************/
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -34,6 +34,46 @@
* Helper functions
******************************************************************************/
static res_T
+matte_shade
+ (const struct ssol_material* mtl,
+ const struct surface_fragment* fragment,
+ const double wavelength, /* In nanometer */
+ struct ssf_bsdf* bsdf)
+{
+ struct ssf_bxdf* brdf = NULL;
+ const struct ssol_matte_shader* shader;
+ double normal[3];
+ double reflectivity;
+ res_T res;
+ ASSERT(mtl && fragment && mtl->type == MATERIAL_MATTE);
+ ASSERT(bsdf);
+
+ shader = &mtl->data.matte;
+
+ /* Fetch material attribs */
+ shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos,
+ fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, normal);
+ shader->reflectivity(mtl->dev, mtl->buf, wavelength, fragment->pos,
+ fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, &reflectivity);
+
+ /* Setup the BRDF */
+ res = ssf_bxdf_create(mtl->dev->allocator, &ssf_lambertian_reflection, &brdf);
+ if(res != RES_OK) goto error;
+ res = ssf_lambertian_reflection_setup(brdf, reflectivity);
+ if(res != RES_OK) goto error;
+
+ /* Setup the BSDF */
+ res = ssf_bsdf_add(bsdf, brdf, 1.0);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(brdf) SSF(bxdf_ref_put(brdf));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
mirror_shade
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
@@ -113,15 +153,21 @@ material_release(ref_T* ref)
SSOL(device_ref_put(dev));
}
-static INLINE res_T
-shader_ok(const struct ssol_mirror_shader* shader)
+static INLINE int
+check_shader_mirror(const struct ssol_mirror_shader* shader)
{
- if(!shader
- || !shader->normal
- || !shader->reflectivity
- || !shader->roughness)
- return RES_BAD_ARG;
- return RES_OK;
+ return shader
+ && shader->normal
+ && shader->reflectivity
+ && shader->roughness;
+}
+
+static INLINE int
+check_shader_matte(const struct ssol_matte_shader* shader)
+{
+ return shader
+ && shader->normal
+ && shader->reflectivity;
}
/*******************************************************************************
@@ -205,16 +251,33 @@ ssol_material_create_mirror
}
res_T
+ssol_material_create_matte
+ (struct ssol_device* dev, struct ssol_material** out_material)
+{
+ return ssol_material_create(dev, out_material, MATERIAL_MATTE);
+}
+
+res_T
ssol_mirror_set_shader
(struct ssol_material* material, const struct ssol_mirror_shader* shader)
{
if(!material
|| material->type != MATERIAL_MIRROR
- || shader_ok(shader) != RES_OK)
+ || !check_shader_mirror(shader))
return RES_BAD_ARG;
-
material->data.mirror = *shader;
+ return RES_OK;
+}
+res_T
+ssol_matte_set_shader
+ (struct ssol_material* material, const struct ssol_matte_shader* shader)
+{
+ if(!material
+ || material->type != MATERIAL_MATTE
+ || !check_shader_matte(shader))
+ return RES_BAD_ARG;
+ material->data.matte = *shader;
return RES_OK;
}
@@ -302,6 +365,9 @@ material_shade
/* Specific material shading */
switch(mtl->type) {
+ case MATERIAL_MATTE:
+ res = matte_shade(mtl, fragment, wavelength, bsdf);
+ break;
case MATERIAL_MIRROR:
res = mirror_shade(mtl, fragment, wavelength, bsdf);
break;
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -35,8 +35,9 @@ static const struct surface_fragment SURFACE_FRAGMENT_NULL =
SURFACE_FRAGMENT_NULL__;
enum material_type {
- MATERIAL_VIRTUAL,
+ MATERIAL_MATTE,
MATERIAL_MIRROR,
+ MATERIAL_VIRTUAL,
MATERIAL_TYPES_COUNT__
};
@@ -44,6 +45,7 @@ struct ssol_material {
enum material_type type;
union {
+ struct ssol_matte_shader matte;
struct ssol_mirror_shader mirror;
} data;
diff --git a/src/test_ssol_material.c b/src/test_ssol_material.c
@@ -26,7 +26,8 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct ssol_device* dev;
struct ssol_material* material;
- struct ssol_mirror_shader shader = SSOL_MIRROR_SHADER_NULL;
+ struct ssol_mirror_shader mirror = SSOL_MIRROR_SHADER_NULL;
+ struct ssol_matte_shader matte = SSOL_MATTE_SHADER_NULL;
struct ssol_param_buffer* pbuf = NULL;
(void) argc, (void) argv;
@@ -52,31 +53,31 @@ main(int argc, char** argv)
CHECK(ssol_param_buffer_create(dev, 32, &pbuf), RES_OK);
- shader.normal = get_shader_normal;
- shader.reflectivity = get_shader_reflectivity;
- shader.roughness = get_shader_roughness;
+ mirror.normal = get_shader_normal;
+ mirror.reflectivity = get_shader_reflectivity;
+ mirror.roughness = get_shader_roughness;
- CHECK(ssol_mirror_set_shader(NULL, &shader), RES_BAD_ARG);
+ CHECK(ssol_mirror_set_shader(NULL, &mirror), RES_BAD_ARG);
CHECK(ssol_mirror_set_shader(material, NULL), RES_BAD_ARG);
- CHECK(ssol_mirror_set_shader(material, &shader), RES_OK);
- CHECK(ssol_mirror_set_shader(material, &shader), RES_OK);
+ CHECK(ssol_mirror_set_shader(material, &mirror), RES_OK);
+ CHECK(ssol_mirror_set_shader(material, &mirror), RES_OK);
CHECK(ssol_material_set_param_buffer(NULL, NULL), RES_BAD_ARG);
CHECK(ssol_material_set_param_buffer(material, NULL), RES_BAD_ARG);
CHECK(ssol_material_set_param_buffer(NULL, pbuf), RES_BAD_ARG);
CHECK(ssol_material_set_param_buffer(material, pbuf), RES_OK);
- shader.normal = NULL;
- CHECK(ssol_mirror_set_shader(material, &shader), RES_BAD_ARG);
- shader.normal = get_shader_normal;
+ mirror.normal = NULL;
+ CHECK(ssol_mirror_set_shader(material, &mirror), RES_BAD_ARG);
+ mirror.normal = get_shader_normal;
- shader.reflectivity = NULL;
- CHECK(ssol_mirror_set_shader(material, &shader), RES_BAD_ARG);
- shader.reflectivity = get_shader_reflectivity;
+ mirror.reflectivity = NULL;
+ CHECK(ssol_mirror_set_shader(material, &mirror), RES_BAD_ARG);
+ mirror.reflectivity = get_shader_reflectivity;
- shader.roughness = NULL;
- CHECK(ssol_mirror_set_shader(material, &shader), RES_BAD_ARG);
- shader.roughness = get_shader_roughness;
+ mirror.roughness = NULL;
+ CHECK(ssol_mirror_set_shader(material, &mirror), RES_BAD_ARG);
+ mirror.roughness = get_shader_roughness;
CHECK(ssol_material_ref_put(material), RES_OK);
@@ -87,6 +88,25 @@ main(int argc, char** argv)
CHECK(ssol_material_ref_put(material), RES_OK);
CHECK(ssol_param_buffer_ref_put(pbuf), RES_OK);
+ CHECK(ssol_material_create_matte(NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_material_create_matte(dev, NULL), RES_BAD_ARG);
+ CHECK(ssol_material_create_matte(NULL, &material), RES_BAD_ARG);
+ CHECK(ssol_material_create_matte(dev, &material), RES_OK);
+
+ matte.normal = get_shader_normal;
+ matte.reflectivity = get_shader_reflectivity;
+ CHECK(ssol_matte_set_shader(NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_matte_set_shader(material, NULL), RES_BAD_ARG);
+ CHECK(ssol_matte_set_shader(NULL, &matte), RES_BAD_ARG);
+ CHECK(ssol_matte_set_shader(material, &matte), RES_OK);
+
+ matte.normal = NULL;
+ CHECK(ssol_matte_set_shader(material, &matte), RES_BAD_ARG);
+ matte.normal = get_shader_normal;
+ matte.reflectivity = NULL;
+ CHECK(ssol_matte_set_shader(material, &matte), RES_BAD_ARG);
+
+ CHECK(ssol_material_ref_put(material), RES_OK);
CHECK(ssol_device_ref_put(dev), RES_OK);
logger_release(&logger);