commit fffb2dd7c9bd659812229a1cd8667d3308ee535b
parent 897e5a1bf41fe278d83a8a6c6aed274473c66efb
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 5 Apr 2017 15:40:29 +0200
Handle normal perturbation in the "draft" rendering
Refactor how the normal perturbation is handled in the material shading.
Diffstat:
5 files changed, 96 insertions(+), 86 deletions(-)
diff --git a/src/ssol_draw_draft.c b/src/ssol_draw_draft.c
@@ -17,6 +17,7 @@
#include "ssol_camera.h"
#include "ssol_device_c.h"
#include "ssol_draw.h"
+#include "ssol_material_c.h"
#include "ssol_object_c.h"
#include "ssol_scene_c.h"
#include "ssol_shape_c.h"
@@ -41,6 +42,7 @@ Li
double val[3])
{
const float range[2] = {0, FLT_MAX};
+ struct surface_fragment frag;
struct ray_data ray_data = RAY_DATA_NULL;
struct s3d_hit hit;
ASSERT(scn && view && org && dir && val);
@@ -52,9 +54,11 @@ Li
d3_splat(val, 0);
} else {
struct ssol_instance* inst;
+ struct ssol_material* mtl;
const struct shaded_shape* sshape;
size_t isshape;
- float N[3]={0};
+ double o[3], wi[3];
+ double N[3]={0};
/* Retrieve the hit shaded shape */
inst = *htable_instance_find(&scn->instances_rt, &hit.prim.inst_id);
@@ -65,12 +69,25 @@ Li
/* Retrieve and normalized the hit normal */
switch(sshape->shape->type) {
- case SHAPE_MESH: f3_normalize(N, hit.normal); break;
- case SHAPE_PUNCHED: f3_normalize(N, f3_set_d3(N, ray_data.N)); break;
+ case SHAPE_MESH: d3_normalize(N, d3_set_f3(N, hit.normal)); break;
+ case SHAPE_PUNCHED: d3_normalize(N, ray_data.N); break;
default: FATAL("Unreachable code"); break;
}
- ASSERT(f3_is_normalized(N));
- d3_splat(val, fabs(f3_dot(N, dir)));
+
+ d3_set_f3(o, org);
+ d3_set_f3(wi, dir);
+ if(d3_dot(N, wi) < 0) {
+ mtl = sshape->mtl_front;
+ } else {
+ mtl = sshape->mtl_back;
+ d3_minus(N, N);
+ }
+
+ surface_fragment_setup(&frag, o, wi, N, &hit.prim, hit.uv);
+ material_shade_normal(mtl, &frag, 1/*TODO wavelength*/, frag.Ns);
+
+ ASSERT(d3_is_normalized(frag.Ns));
+ d3_splat(val, fabs(d3_dot(frag.Ns, wi)));
}
}
@@ -84,14 +101,14 @@ draw_pixel
const float pix_sz[2], /* Normalized pixel size */
const size_t nsamples,
double pixel[3],
- void* ctx)
+ void* data)
{
- struct darray_float* samples = ctx;
+ struct darray_float* samples = data;
float samp[2];
float ray_org[3], ray_dir[3];
double sum[3] = {0, 0, 0};
size_t i;
- ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel && ctx);
+ ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel && data);
(void)ithread;
FOR_EACH(i, 0, nsamples) {
@@ -135,6 +152,7 @@ ssol_draw_draft
if(!scn || !spp) return RES_BAD_ARG;
darray_float_init(scn->dev->allocator, &samples);
+
res = darray_float_reserve(&samples, spp * 2/*#dimensions*/);
if(res != RES_OK) goto error;
diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c
@@ -204,8 +204,8 @@ Li(struct ssol_scene* scn,
surface_fragment_setup(&frag, o, wo, N, &hit.prim, hit.uv);
SSF(bsdf_clear(ctx->bsdf));
- res = material_shade_rendering
- (mtl, &frag, 1/*TODO wavelength*/, &medium, ctx->bsdf);
+ res = material_setup_bsdf
+ (mtl, &frag, 1/*TODO wavelength*/, &medium, 1/*Rendering*/, ctx->bsdf);
if(res != RES_OK) goto error;
/* Update the ray */
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -34,7 +34,7 @@
* Helper functions
******************************************************************************/
static res_T
-dielectric_shade
+setup_dielectric_bsdf
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
@@ -44,18 +44,11 @@ dielectric_shade
struct ssf_bxdf* brdf = NULL;
struct ssf_bxdf* btdf = NULL;
struct ssf_fresnel* fresnel = NULL;
- const struct ssol_dielectric_shader* shader;
double eta_i, eta_t;
- double N[3];
res_T res = RES_OK;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC);
ASSERT(medium && bsdf);
-
- shader = &mtl->data.dielectric;
-
- /* Fetch material attribs */
- shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos, fragment->Ng,
- fragment->Ns, fragment->uv, fragment->dir, N);
+ (void)wavelength, (void)fragment;
if(!MEDIA_EQ(medium, &mtl->out_medium)) {
log_error(mtl->dev, "Inconsistent medium description.\n");
@@ -91,7 +84,7 @@ error:
}
static res_T
-matte_shade
+setup_matte_bsdf
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
@@ -99,7 +92,6 @@ matte_shade
{
struct ssf_bxdf* brdf = NULL;
const struct ssol_matte_shader* shader;
- double normal[3];
double reflectivity;
res_T res;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_MATTE);
@@ -108,8 +100,6 @@ matte_shade
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);
@@ -131,7 +121,7 @@ error:
}
static res_T
-mirror_shade
+setup_mirror_bsdf
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
@@ -142,7 +132,6 @@ mirror_shade
struct ssf_fresnel* fresnel = NULL;
struct ssf_microfacet_distribution* distrib = NULL;
const struct ssol_mirror_shader* shader;
- double normal[3];
double roughness;
double reflectivity;
res_T res;
@@ -152,8 +141,6 @@ mirror_shade
shader = &mtl->data.mirror;
/* 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);
shader->roughness(mtl->dev, mtl->buf, wavelength, fragment->pos,
@@ -207,15 +194,13 @@ error:
}
static res_T
-thin_dielectric_shade
+setup_thin_dielectric_bsdf
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
struct ssf_bsdf* bsdf)
{
struct ssf_bxdf* bxdf = NULL;
- const struct ssol_thin_dielectric_shader* shader;
- double N[3];
double thickness;
double absorptivity;
double eta_i;
@@ -223,12 +208,8 @@ thin_dielectric_shade
res_T res = RES_OK;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_THIN_DIELECTRIC);
ASSERT(bsdf);
+ (void)wavelength, (void)fragment;
- shader = &mtl->data.thin_dielectric.shader;
-
- /* Fetch material attribs */
- shader->normal(mtl->dev, mtl->buf, wavelength, fragment->pos,
- fragment->Ng, fragment->Ns, fragment->uv, fragment->dir, N);
eta_i = mtl->out_medium.refractive_index;
eta_t = mtl->data.thin_dielectric.slab_medium.refractive_index;
absorptivity = mtl->data.thin_dielectric.slab_medium.absorptivity;
@@ -253,39 +234,6 @@ error:
goto exit;
}
-static INLINE res_T
-shade
- (const struct ssol_material* mtl,
- const struct surface_fragment* fragment,
- const double wavelength, /* In nanometer */
- const int rendering, /* Is material used for rendering */
- const struct ssol_medium* medium,
- struct ssf_bsdf* bsdf)
-{
- res_T res = RES_OK;
- ASSERT(mtl);
-
- /* Specific material shading */
- switch(mtl->type) {
- case SSOL_MATERIAL_DIELECTRIC:
- res = dielectric_shade
- (mtl, fragment, wavelength, medium, bsdf);
- break;
- case SSOL_MATERIAL_MATTE:
- res = matte_shade(mtl, fragment, wavelength, bsdf);
- break;
- case SSOL_MATERIAL_MIRROR:
- res = mirror_shade(mtl, fragment, wavelength, rendering, bsdf);
- break;
- case SSOL_MATERIAL_THIN_DIELECTRIC:
- res = thin_dielectric_shade(mtl, fragment, wavelength, bsdf);
- break;
- case SSOL_MATERIAL_VIRTUAL: /* Nothing to shade */ break;
- default: FATAL("Unreachable code\n"); break;
- }
- return res;
-}
-
static INLINE int
check_shader_dielectric(const struct ssol_dielectric_shader* shader)
{
@@ -593,28 +541,72 @@ surface_fragment_setup
}
}
-res_T
-material_shade
+void
+material_shade_normal
(const struct ssol_material* mtl,
- const struct surface_fragment* fragment,
- const double wavelength, /* In nanometer */
- const struct ssol_medium* medium,
- struct ssf_bsdf* bsdf)
+ const struct surface_fragment* frag,
+ const double wavelength,
+ double N[3])
{
- return shade(mtl, fragment, wavelength, 0, medium, bsdf);
+ ASSERT(mtl && frag && N);
+
+ if(mtl->type == SSOL_MATERIAL_VIRTUAL) {
+ d3_set(N, frag->Ns);
+ } else {
+ ssol_shader_getter_T normal;
+ switch(mtl->type) {
+ case SSOL_MATERIAL_DIELECTRIC:
+ normal = mtl->data.dielectric.normal;
+ break;
+ case SSOL_MATERIAL_MATTE:
+ normal = mtl->data.matte.normal;
+ break;
+ case SSOL_MATERIAL_MIRROR:
+ normal = mtl->data.mirror.normal;
+ break;
+ case SSOL_MATERIAL_THIN_DIELECTRIC:
+ normal = mtl->data.thin_dielectric.shader.normal;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ normal(mtl->dev, mtl->buf, wavelength, frag->pos, frag->Ng, frag->Ns,
+ frag->uv, frag->dir, N);
+ }
}
res_T
-material_shade_rendering
+material_setup_bsdf
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
const struct ssol_medium* medium,
+ const int rendering, /* Is BSDF used for rendering */
struct ssf_bsdf* bsdf)
{
- return shade(mtl, fragment, wavelength, 1, medium, bsdf);
+ res_T res = RES_OK;
+ ASSERT(mtl);
+
+ switch(mtl->type) {
+ case SSOL_MATERIAL_DIELECTRIC:
+ res = setup_dielectric_bsdf
+ (mtl, fragment, wavelength, medium, bsdf);
+ break;
+ case SSOL_MATERIAL_MATTE:
+ res = setup_matte_bsdf(mtl, fragment, wavelength, bsdf);
+ break;
+ case SSOL_MATERIAL_MIRROR:
+ res = setup_mirror_bsdf(mtl, fragment, wavelength, rendering, bsdf);
+ break;
+ case SSOL_MATERIAL_THIN_DIELECTRIC:
+ res = setup_thin_dielectric_bsdf(mtl, fragment, wavelength, bsdf);
+ break;
+ case SSOL_MATERIAL_VIRTUAL: /* Nothing to shade */ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ return res;
}
+
res_T
material_get_next_medium
(const struct ssol_material* mtl,
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -71,21 +71,20 @@ surface_fragment_setup
const struct s3d_primitive* primitive,
const float uv[2]);
-extern LOCAL_SYM res_T
-material_shade
+extern LOCAL_SYM void
+material_shade_normal
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
- const double wavelength, /* In nanometer */
- const struct ssol_medium* medium, /* Current medium */
- struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */
+ const double wavelength,
+ double N[3]);
-/* Material shading for rendering purposes */
extern LOCAL_SYM res_T
-material_shade_rendering
+material_setup_bsdf
(const struct ssol_material* mtl,
const struct surface_fragment* fragment,
const double wavelength, /* In nanometer */
- const struct ssol_medium* medium,
+ const struct ssol_medium* medium, /* Current medium */
+ const int rendering, /* Is material used for rendering purposes */
struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */
extern LOCAL_SYM res_T
@@ -95,3 +94,4 @@ material_get_next_medium
struct ssol_medium* next_medium);
#endif /* SSOL_MATERIAL_C_H */
+
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -378,7 +378,7 @@ point_shade
/* Shade the surface fragment */
mtl = point_get_material(pt);
SSF(bsdf_clear(bsdf));
- res = material_shade(mtl, &frag, pt->wl, medium, bsdf);
+ res = material_setup_bsdf(mtl, &frag, pt->wl, medium, 0, bsdf);
if(res != RES_OK) return res;
/* By convention, Star-SF assumes that incoming and reflected