solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

commit a3fc7537eee74c31bbecd3e63c227709b7142c18
parent 2d3e9fefb5f0680562b61050152539e3bcea5081
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 13 Jul 2016 16:43:12 +0200

Implement the internal material_shade function

Fill a BRDF composite with respect to the given material properties.

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssol.h | 7++++---
Asrc/ssol_c.h | 38++++++++++++++++++++++++++++++++++++++
Msrc/ssol_material.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/ssol_material_c.h | 12++++++++++++
Msrc/ssol_shape.c | 7++++---
Msrc/test_ssol_material.c | 30+++++++++++++++++-------------
7 files changed, 216 insertions(+), 21 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -71,6 +71,7 @@ set(SSOL_FILES_INC ssol_brdf.h ssol_brdf_composite.h ssol_brdf_reflection.h + ssol_c.h ssol_device_c.h ssol_image_c.h ssol_material_c.h diff --git a/src/ssol.h b/src/ssol.h @@ -178,13 +178,14 @@ typedef void const double wavelength, /* In nanometer */ const double P[3], /* World space position */ const double Ng[3], /* World space geometry normal */ - const double uv[2], /* Parametric coordinates */ - const double wo[3], /* Incident direction */ + const double Ns[3], /* World space shading normal */ + const double uv[2], /* Texture coordinates */ + const double w[3], /* Incoming direction. Point toward the surface */ double* val); /* Returned value */ /* Material descriptors */ struct ssol_mirror_shader { - ssol_shader_getter_T shading_normal; + ssol_shader_getter_T normal; ssol_shader_getter_T reflectivity; ssol_shader_getter_T diffuse_specular_ratio; ssol_shader_getter_T roughness; diff --git a/src/ssol_c.h b/src/ssol_c.h @@ -0,0 +1,38 @@ +/* Copyright (C) CNRS 2016 + * + * 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/>. */ + +#ifndef SSOL_C_H +#define SSOL_C_H + +#include "ssol.h" +#include <star/s3d.h> + +#define SSOL_TO_S3D_POSITION S3D_POSITION +#define SSOL_TO_S3D_NORMAL S3D_ATTRIB_0 +#define SSOL_TO_S3D_TEXCOORD S3D_ATTRIB_1 + +static FINLINE enum s3d_attrib_usage +ssol_to_s3d_attrib_usage(const enum ssol_attrib_usage usage) +{ + switch(usage) { + case SSOL_POSITION: return SSOL_TO_S3D_POSITION; + case SSOL_NORMAL: return SSOL_TO_S3D_NORMAL; + case SSOL_TEXCOORD: return SSOL_TO_S3D_TEXCOORD; + default: FATAL("Unreachable code\n"); break; + } +} + +#endif /* SSOL_C_H */ + diff --git a/src/ssol_material.c b/src/ssol_material.c @@ -14,16 +14,61 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssol.h" +#include "ssol_brdf_composite.h" +#include "ssol_brdf_reflection.h" +#include "ssol_c.h" #include "ssol_material_c.h" #include "ssol_device_c.h" +#include <rsys/double3.h> +#include <rsys/float3.h> +#include <rsys/float33.h> +#include <rsys/ref_count.h> #include <rsys/rsys.h> #include <rsys/mem_allocator.h> -#include <rsys/ref_count.h> + +#include <math.h> /******************************************************************************* * Helper functions ******************************************************************************/ +static res_T +mirror_shade + (const struct ssol_material* mtl, + const double wavelength, /* In nanometer */ + const double P[3], /* World space position */ + const double Ng[3], /* World space geometry normal */ + const double Ns[3], /* World space shading normal */ + const double uv[2], /* Texture coordinates */ + const double w[3], /* Incoming direction. Point toward the surface */ + struct brdf_composite* brdfs) +{ + struct brdf* reflect = NULL; + const struct ssol_mirror_shader* shader; + double normal[3]; + double R; /* Reflectivity */ + res_T res; + ASSERT(mtl && P && Ng && Ns && uv && w && mtl->type == MATERIAL_MIRROR); + + shader = &mtl->data.mirror; + + /* FIXME currently the mirror material is a purely reflective BRDF. Discard + * the diffuse_specular_ration & the rougness parameters */ + shader->normal(mtl->dev, wavelength, P, Ng, Ns, uv, w, normal); + shader->reflectivity(mtl->dev, wavelength, P, Ng, Ns, uv, w, &R); + + if(RES_OK != (res = brdf_reflection_create(mtl->dev, &reflect))) goto error; + if(RES_OK != (res = brdf_reflection_setup(reflect, R))) goto error; + if(RES_OK != (res = brdf_composite_add(brdfs, reflect))) goto error; + brdf_ref_put(reflect); + +exit: + if(reflect) brdf_ref_put(reflect); + return res; +error: + goto exit; +} + static void material_release(ref_T* ref) { @@ -40,7 +85,7 @@ static INLINE res_T shader_ok(const struct ssol_mirror_shader* shader) { if(!shader - || !shader->shading_normal + || !shader->normal || !shader->reflectivity || !shader->diffuse_specular_ratio || !shader->roughness) @@ -142,3 +187,96 @@ ssol_material_create_virtual return ssol_material_create(dev, out_material, MATERIAL_VIRTUAL); } +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +material_shade + (const struct ssol_material* mtl, + const double wavelength, /* In nanometer */ + const struct s3d_hit* hit, /* Hit point to shade */ + const float dir[3], /* Incoming direction */ + struct brdf_composite* brdfs) /* Container of BRDFs */ +{ + struct s3d_attrib attr; + double w[3]; /* Incoming direction */ + double P[3]; /* World space hit position */ + double Ng[3]; /* World space normalized geometry normal */ + double Ns[3]; /* World space normalized shading normal */ + double uv[2]; /* Texture coordinates */ + double len; + char has_texcoord, has_normal; + res_T res = RES_OK; + ASSERT(mtl && dir && hit && brdfs); + + /* Convert the incoming direction in double */ + w[0] = (double)dir[0]; + w[1] = (double)dir[1]; + w[2] = (double)dir[2]; + + /* Retrieve the hit position */ + S3D(primitive_get_attrib(&hit->prim, S3D_POSITION, hit->uv, &attr)); + ASSERT(attr.type == S3D_FLOAT3); + P[0] = (double)attr.value[0]; + P[1] = (double)attr.value[1]; + P[2] = (double)attr.value[2]; + + /* Normalize the geometry normal */ + len = sqrt(f3_len(hit->normal)); + Ng[0] = (double)hit->normal[0] / len; + Ng[1] = (double)hit->normal[1] / len; + Ng[2] = (double)hit->normal[2] / len; + + /* Retrieve the tex coord */ + S3D(primitive_has_attrib(&hit->prim, SSOL_TO_S3D_TEXCOORD, &has_texcoord)); + if(!has_texcoord) { + uv[0] = (double)hit->uv[0]; + uv[1] = (double)hit->uv[1]; + } else { + S3D(primitive_get_attrib(&hit->prim, SSOL_TO_S3D_TEXCOORD, hit->uv, &attr)); + ASSERT(attr.type == S3D_FLOAT2); + uv[0] = (double)attr.value[0]; + uv[1] = (double)attr.value[1]; + } + + /* Retrieve and normalize the shading normal in world space */ + S3D(primitive_has_attrib(&hit->prim, SSOL_TO_S3D_NORMAL, &has_normal)); + if(!has_normal) { + d3_set(Ns, Ng); + } else { + float transform[12]; + float vec[3]; + + S3D(primitive_get_attrib(&hit->prim, SSOL_TO_S3D_NORMAL, hit->uv, &attr)); + ASSERT(attr.type == S3D_FLOAT3); + + S3D(primitive_get_transform(&hit->prim, transform)); + /* Check that transform is not "identity" */ + if(!f3_eq(transform + 0, f3(vec, 1.f, 0.f, 0.f)) + && !f3_eq(transform + 3, f3(vec, 0.f, 1.f, 0.f)) + && !f3_eq(transform + 6, f3(vec, 0.f, 0.f, 1.f))) { + /* Transform the normal in world space, i.e. multiply it by the inverse + * transpose of the "object to world" primitive matrix. Since the affine + * part of the 3x4 transformation matrix does not influence the normal + * transformation, use the linear part only. */ + f33_invtrans(transform, transform); + f33_mulf3(attr.value, transform, attr.value); + } + + len = sqrt(f3_len(attr.value)); + Ns[0] = (double)attr.value[0] / len; + Ns[1] = (double)attr.value[1] / len; + Ns[2] = (double)attr.value[2] / len; + } + + /* Specific material shading */ + switch(mtl->type) { + case MATERIAL_MIRROR: + res = mirror_shade(mtl, wavelength, P, Ng, Ns, uv, w, brdfs); + break; + default: FATAL("Unreachable code\n"); break; + } + + return res; +} + diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h @@ -18,6 +18,9 @@ #include <rsys/ref_count.h> +struct brdf_composite; +struct s3d_hit; + enum material_type { MATERIAL_VIRTUAL, MATERIAL_MIRROR, @@ -37,4 +40,13 @@ struct ssol_material { ref_T ref; }; +extern LOCAL_SYM res_T +material_shade + (const struct ssol_material* mtl, + const double wavelength, /* In nanometer */ + const struct s3d_hit* hit, /* Hit point to shade */ + const float w[3], /* Incoming direction */ + struct brdf_composite* brdfs); /* Container of BRDFs */ + #endif /* SSOL_MATERIAL_C_H */ + diff --git a/src/ssol_shape.c b/src/ssol_shape.c @@ -14,6 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ssol.h" +#include "ssol_c.h" #include "ssol_shape_c.h" #include "ssol_device_c.h" @@ -305,15 +306,15 @@ ssol_mesh_setup attrib3[i].get = attribs[i].get; switch (attribs[i].usage) { case SSOL_POSITION: - attrib3[i].usage = S3D_POSITION; + attrib3[i].usage = SSOL_TO_S3D_POSITION; attrib3[i].type = S3D_FLOAT3; break; case SSOL_NORMAL: - attrib3[i].usage = S3D_ATTRIB_0; + attrib3[i].usage = SSOL_TO_S3D_NORMAL; attrib3[i].type = S3D_FLOAT3; break; case SSOL_TEXCOORD: - attrib3[i].usage = S3D_ATTRIB_1; + attrib3[i].usage = SSOL_TO_S3D_TEXCOORD; attrib3[i].type = S3D_FLOAT2; break; default: diff --git a/src/test_ssol_material.c b/src/test_ssol_material.c @@ -19,18 +19,19 @@ #include <rsys/logger.h> static void -get_shading_normal +get_normal (struct ssol_device* dev, const double wavelength, const double P[3], const double Ng[3], + const double Ns[3], const double uv[2], - const double wo[3], + const double w[3], double* val) { int i; - (void) dev; (void) wavelength; (void) P; (void) uv; (void) wo; - for (i = 0; i < 3; i++) val[i] = Ng[i]; + (void)dev, (void)wavelength, (void)P, (void)Ng, (void)uv, (void)w; + FOR_EACH(i, 0, 3) val[i] = Ns[i]; } static void @@ -39,11 +40,12 @@ get_reflectivity const double wavelength, const double P[3], const double Ng[3], + const double Ns[3], const double uv[2], - const double wo[3], + const double w[3], double* val) { - (void) dev; (void) wavelength; (void) P; (void) Ng; (void) uv; (void) wo; + (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; *val = 1; } @@ -53,11 +55,12 @@ get_diffuse_specular_ratio const double wavelength, const double P[3], const double Ng[3], + const double Ns[3], const double uv[2], - const double wo[3], + const double w[3], double* val) { - (void) dev; (void) wavelength; (void) P; (void) Ng; (void) uv; (void) wo; + (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; *val = 0; } @@ -67,11 +70,12 @@ get_roughness const double wavelength, const double P[3], const double Ng[3], + const double Ns[3], const double uv[2], - const double wo[3], + const double w[3], double* val) { - (void) dev; (void) wavelength; (void) P; (void) Ng; (void) uv; (void) wo; + (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; *val = 0; } @@ -107,7 +111,7 @@ main(int argc, char** argv) CHECK(ssol_material_ref_put(NULL), RES_BAD_ARG); CHECK(ssol_material_ref_put(material), RES_OK); - shader.shading_normal = get_shading_normal; + shader.normal = get_normal; shader.reflectivity = get_reflectivity; shader.diffuse_specular_ratio = get_diffuse_specular_ratio; shader.roughness = get_roughness; @@ -116,9 +120,9 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(material, NULL), RES_BAD_ARG); CHECK(ssol_mirror_set_shader(material, &shader), RES_OK); - shader.shading_normal = NULL; + shader.normal = NULL; CHECK(ssol_mirror_set_shader(material, &shader), RES_BAD_ARG); - shader.shading_normal = get_shading_normal; + shader.normal = get_normal; shader.reflectivity = NULL; CHECK(ssol_mirror_set_shader(material, &shader), RES_BAD_ARG);