solstice-solver

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

commit 12012976ef1bb1b87d1df903b6b04317ee07490f
parent 385e7b8ece4d1cd4cbb095a7c7826419fcc12c60
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 20 Jul 2016 17:02:30 +0200

Write hit data if the hit instance is a receiver

Diffstat:
Msrc/ssol_c.h | 7++++++-
Msrc/ssol_material.c | 90++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/ssol_material_c.h | 18++++++++++++++++--
Msrc/ssol_scene.c | 22++++++++++++++++++++--
4 files changed, 88 insertions(+), 49 deletions(-)

diff --git a/src/ssol_c.h b/src/ssol_c.h @@ -25,7 +25,12 @@ struct ray_data { struct ssol_scene* scene; /* Scene in which the ray is traced */ - struct s3d_primitive prim_from; /* Primitive from which the scene start */ + struct s3d_primitive prim_from; /* Primitive from which the ray starts */ + unsigned path_id; /* Identifier of the path to which the ray belongs to */ + unsigned ray_id; /* Identifier of the ray into the path */ + double radiance; /* Current path radiance in W.sr^-1.m^-2 */ + double wavelength; /* Wavelength of the current path in nanometer */ + FILE* stream; }; static FINLINE enum s3d_attrib_usage diff --git a/src/ssol_material.c b/src/ssol_material.c @@ -35,12 +35,8 @@ static res_T mirror_shade (const struct ssol_material* mtl, + const struct surface_fragment* fragment, 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; @@ -48,14 +44,17 @@ mirror_shade double normal[3]; double R; /* Reflectivity */ res_T res; - ASSERT(mtl && P && Ng && Ns && uv && w && mtl->type == MATERIAL_MIRROR); + ASSERT(mtl && fragment && mtl->type == MATERIAL_MIRROR); + ASSERT(brdfs); shader = &mtl->data.mirror; /* FIXME currently the mirror material is a purely reflective BRDF. Discard * the diffuse_specular_ratio & 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); + shader->normal(mtl->dev, wavelength, fragment->pos, fragment->Ng, + fragment->Ns, fragment->uv, fragment->dir, normal); + shader->reflectivity(mtl->dev, wavelength, fragment->pos, fragment->Ng, + fragment->Ns, fragment->uv, fragment->dir, &R); if(RES_OK != (res = brdf_reflection_create(mtl->dev, &reflect))) goto error; if(RES_OK != (res = brdf_reflection_setup(reflect, R))) goto error; @@ -189,59 +188,50 @@ ssol_material_create_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 */ +void +surface_fragment_setup + (struct surface_fragment* fragment, + const float ray_org[3], + const float ray_dir[3], + const struct s3d_hit* hit) { 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); + ASSERT(fragment && ray_org && ray_dir && hit); - /* Convert the incoming direction in double */ - w[0] = (double)dir[0]; - w[1] = (double)dir[1]; - w[2] = (double)dir[2]; + /* Setup the incoming direction */ + fragment->dir[0] = ray_dir[0]; + fragment->dir[1] = ray_dir[1]; + fragment->dir[2] = ray_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]; + /* Setup the surface position */ + fragment->pos[0] = ray_org[0] + ray_dir[0] * hit->distance; + fragment->pos[1] = ray_org[1] + ray_dir[1] * hit->distance; + fragment->pos[2] = ray_org[2] + ray_dir[2] * hit->distance; /* 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; + fragment->Ng[0] = hit->normal[0] / len; + fragment->Ng[1] = hit->normal[1] / len; + fragment->Ng[2] = 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]; + fragment->uv[0] = hit->uv[0]; + fragment->uv[1] = 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]; + fragment->uv[0] = attr.value[0]; + fragment->uv[1] = 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); + d3_set(fragment->Ns, fragment->Ng); } else { float transform[12]; float vec[3]; @@ -263,16 +253,28 @@ material_shade } 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; + fragment->Ns[0] = attr.value[0] / len; + fragment->Ns[1] = attr.value[1] / len; + fragment->Ns[2] = attr.value[2] / len; } +} + +res_T +material_shade + (const struct ssol_material* mtl, + const struct surface_fragment* fragment, + const double wavelength, /* In nanometer */ + struct brdf_composite* brdfs) /* Container of BRDFs */ +{ + res_T res = RES_OK; + ASSERT(mtl); /* Specific material shading */ switch(mtl->type) { case MATERIAL_MIRROR: - res = mirror_shade(mtl, wavelength, P, Ng, Ns, uv, w, brdfs); + res = mirror_shade(mtl, fragment, wavelength, brdfs); break; + case MATERIAL_VIRTUAL: /* Nothing to shade */ break; default: FATAL("Unreachable code\n"); break; } return res; diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h @@ -21,6 +21,14 @@ struct brdf_composite; struct s3d_hit; +struct surface_fragment { + double dir[3]; /* World space incoming direction */ + double pos[3]; /* World space position */ + double Ng[3]; /* Normalized world space primitive normal */ + double Ns[3]; /* Normalized world space shading normal */ + double uv[2]; /* Texture coordinates */ +}; + enum material_type { MATERIAL_VIRTUAL, MATERIAL_MIRROR, @@ -47,12 +55,18 @@ material_get_type(const struct ssol_material* mtl) return mtl->type; } +extern LOCAL_SYM void +surface_fragment_setup + (struct surface_fragment* fragment, + const float ray_org[3], + const float ray_dir[3], + const struct s3d_hit* hit); + extern LOCAL_SYM res_T material_shade (const struct ssol_material* mtl, + const struct surface_fragment* fragment, 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_scene.c b/src/ssol_scene.c @@ -259,6 +259,7 @@ hit_filter_function struct ray_data* rdata; struct ssol_object_instance* instance; struct ssol_material* material; + const char* receiver_name; (void)org, (void)dir, (void)filter_data; ASSERT(rdata); @@ -269,10 +270,27 @@ hit_filter_function return 1; /* Discard self intersection */ instance = scene_get_object_instance_from_s3d_hit(rdata->scene, hit); - material = object_get_material(object_instance_get_object(instance)); - if(material_get_type(material) == MATERIAL_VIRTUAL) + /* Check if the hit surface is a receiver that registers hit data */ + receiver_name = object_instance_get_receiver_name(instance); + if(receiver_name) { + struct surface_fragment frag; + surface_fragment_setup(&frag, org, dir, hit); + fprintf(rdata->stream, "%s %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g)\n", + receiver_name, + rdata->path_id, + rdata->ray_id, + rdata->wavelength, + rdata->radiance, + SPLIT3(frag.pos), + SPLIT3(frag.dir), + SPLIT2(frag.uv)); + } + + material = object_get_material(object_instance_get_object(instance)); + if(material_get_type(material) == MATERIAL_VIRTUAL) { return 1; /* Discard virtual material */ + } return 0; }