commit 95440d240d759b8b4ab38bb3f9ef82bf37cc288f
parent 643459fb2dc5ebe4ef4f3223ad5fff49b8599828
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 10 Mar 2017 16:03:49 +0100
Add absorbed irradiance computations.
Diffstat:
6 files changed, 72 insertions(+), 31 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -307,6 +307,7 @@ struct ssol_mc_global {
struct ssol_mc_receiver {
struct ssol_mc_result integrated_irradiance; /* In W */
+ struct ssol_mc_result integrated_absorbed_irradiance; /* In W */
struct ssol_mc_result absorptivity_loss; /* In W */
struct ssol_mc_result reflectivity_loss; /* In W */
struct ssol_mc_result cos_loss; /* In W TODO remove this */
@@ -318,6 +319,7 @@ struct ssol_mc_receiver {
struct ssol_mc_primitive {
struct ssol_mc_result integrated_irradiance; /* In W */
+ struct ssol_mc_result integrated_absorbed_irradiance; /* In W */
struct ssol_mc_result absorptivity_loss; /* In W */
struct ssol_mc_result reflectivity_loss; /* In W */
struct ssol_mc_result cos_loss; /* In W TODO remove this */
diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c
@@ -166,6 +166,7 @@ ssol_estimator_get_mc_sampled_x_receiver
rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \
} (void)0
SETUP_MC_RESULT(integrated_irradiance);
+ SETUP_MC_RESULT(integrated_absorbed_irradiance);
SETUP_MC_RESULT(absorptivity_loss);
SETUP_MC_RESULT(reflectivity_loss);
SETUP_MC_RESULT(cos_loss);
diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h
@@ -41,6 +41,7 @@ static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__;
******************************************************************************/
#define MC_RECEIVER_DATA \
struct mc_data integrated_irradiance; /* In W */ \
+ struct mc_data integrated_absorbed_irradiance; /* In W */ \
struct mc_data absorptivity_loss; /* In W */ \
struct mc_data reflectivity_loss; /* In W */ \
struct mc_data cos_loss; /* In W */
@@ -49,6 +50,7 @@ static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__;
MC_DATA_NULL__, \
MC_DATA_NULL__, \
MC_DATA_NULL__, \
+ MC_DATA_NULL__, \
MC_DATA_NULL__
struct mc_primitive_1side {
@@ -84,6 +86,7 @@ mc_receiver_1side_init
{
ASSERT(mc);
mc->integrated_irradiance = MC_DATA_NULL;
+ mc->integrated_absorbed_irradiance = MC_DATA_NULL;
mc->absorptivity_loss = MC_DATA_NULL;
mc->reflectivity_loss = MC_DATA_NULL;
mc->cos_loss = MC_DATA_NULL;
@@ -106,6 +109,7 @@ mc_receiver_1side_copy
res_T res = RES_OK;
ASSERT(dst && src);
dst->integrated_irradiance = src->integrated_irradiance;
+ dst->integrated_absorbed_irradiance = src->integrated_absorbed_irradiance;
dst->absorptivity_loss = src->absorptivity_loss;
dst->reflectivity_loss = src->reflectivity_loss;
dst->cos_loss = src->cos_loss;
@@ -123,6 +127,7 @@ mc_receiver_1side_copy_and_release
res_T res = RES_OK;
ASSERT(dst && src);
dst->integrated_irradiance = src->integrated_irradiance;
+ dst->integrated_absorbed_irradiance = src->integrated_absorbed_irradiance;
dst->absorptivity_loss = src->absorptivity_loss;
dst->reflectivity_loss = src->reflectivity_loss;
dst->cos_loss = src->cos_loss;
diff --git a/src/ssol_mc_receiver.c b/src/ssol_mc_receiver.c
@@ -50,6 +50,7 @@ ssol_estimator_get_mc_receiver
rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \
} (void)0
SETUP_MC_RESULT(integrated_irradiance);
+ SETUP_MC_RESULT(integrated_absorbed_irradiance);
SETUP_MC_RESULT(absorptivity_loss);
SETUP_MC_RESULT(reflectivity_loss);
SETUP_MC_RESULT(cos_loss);
@@ -94,6 +95,7 @@ ssol_mc_receiver_get_mc_primitive
prim->Name.SE = prim->Name.V > 0 ? sqrt(prim->Name.V / N) : 0; \
} (void)0
SETUP_MC_RESULT(integrated_irradiance);
+ SETUP_MC_RESULT(integrated_absorbed_irradiance);
SETUP_MC_RESULT(absorptivity_loss);
SETUP_MC_RESULT(reflectivity_loss);
SETUP_MC_RESULT(cos_loss);
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -155,10 +155,12 @@ struct point {
double dir[3];
float uv[2];
double wl; /* Sampled wavelength */
- double weight; /* actual weight */
- double absorptivity_loss;
- double reflectivity_loss;
- double cos_loss;
+ /* MC weights, before and after hit */
+ double incoming_weight, weight;
+ double absorbed_irradiance; /* current hit only */
+ double absorptivity_loss_before, absorptivity_loss;
+ double reflectivity_loss_before, reflectivity_loss;
+ double cos_loss_before, cos_loss;
enum ssol_side_flag side;
};
@@ -172,7 +174,7 @@ struct point {
{0, 0, 0}, /* Direction */ \
{0, 0}, /* UV */ \
0, /* Wavelength */ \
- 0, 0, 0, 0, /* MC weights */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MC weights */ \
SSOL_FRONT /* Side */ \
}
static const struct point POINT_NULL = POINT_NULL__;
@@ -365,12 +367,27 @@ point_shade
r = ssf_bsdf_sample(bsdf, rng, wi, frag.Ns, dir, &pdf);
ASSERT(0 <= r && r <= 1);
- pt->reflectivity_loss += (1 - r) * pt->weight;
- pt->weight *= r;
+ pt->incoming_weight = pt->weight;
+ pt->absorptivity_loss_before = pt->absorptivity_loss;
+ pt->reflectivity_loss_before = pt->reflectivity_loss;
+ pt->cos_loss_before = pt->cos_loss;
+ pt->absorbed_irradiance = (1 - r) * pt->weight;
+ pt->reflectivity_loss += pt->absorbed_irradiance;
+ pt->weight = pt->incoming_weight - pt->absorbed_irradiance;
return RES_OK;
}
+static FINLINE void
+point_hit_virtual(struct point* pt)
+{
+ pt->absorbed_irradiance = 0;
+ pt->incoming_weight = pt->weight;
+ pt->absorptivity_loss_before = pt->absorptivity_loss;
+ pt->reflectivity_loss_before = pt->reflectivity_loss;
+ pt->cos_loss_before = pt->cos_loss;
+}
+
static FINLINE int
point_is_receiver(const struct point* pt)
{
@@ -463,6 +480,7 @@ accum_mc_receivers_1side
dst->Name.sqr_weight += src->Name.sqr_weight; \
} (void)0
ACCUM_WEIGHT(integrated_irradiance);
+ ACCUM_WEIGHT(integrated_absorbed_irradiance);
ACCUM_WEIGHT(absorptivity_loss);
ACCUM_WEIGHT(reflectivity_loss);
ACCUM_WEIGHT(cos_loss);
@@ -479,6 +497,7 @@ accum_mc_receivers_1side
dst_mc_prim->Name.sqr_weight += src_mc_prim->Name.sqr_weight; \
} (void)0
ACCUM_WEIGHT(integrated_irradiance);
+ ACCUM_WEIGHT(integrated_absorbed_irradiance);
ACCUM_WEIGHT(absorptivity_loss);
ACCUM_WEIGHT(reflectivity_loss);
ACCUM_WEIGHT(cos_loss);
@@ -565,10 +584,11 @@ update_mc
mc_rcv1->Name.weight += (W); \
mc_rcv1->Name.sqr_weight += (W)*(W); \
} (void)0
- ACCUM_WEIGHT(integrated_irradiance, pt->weight);
- ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss);
- ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss);
- ACCUM_WEIGHT(cos_loss, pt->cos_loss);
+ ACCUM_WEIGHT(integrated_irradiance, pt->incoming_weight);
+ ACCUM_WEIGHT(integrated_absorbed_irradiance, pt->absorbed_irradiance);
+ ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss_before);
+ ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss_before);
+ ACCUM_WEIGHT(cos_loss, pt->cos_loss_before);
#undef ACCUM_WEIGHT
/* Per-sampled/receiver MC accumulation */
@@ -579,10 +599,11 @@ update_mc
mc_samp_x_rcv1->Name.weight += (W); \
mc_samp_x_rcv1->Name.sqr_weight += (W)*(W); \
} (void)0
- ACCUM_WEIGHT(integrated_irradiance, pt->weight);
- ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss);
- ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss);
- ACCUM_WEIGHT(cos_loss, pt->cos_loss);
+ ACCUM_WEIGHT(integrated_irradiance, pt->incoming_weight);
+ ACCUM_WEIGHT(integrated_absorbed_irradiance, pt->absorbed_irradiance);
+ ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss_before);
+ ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss_before);
+ ACCUM_WEIGHT(cos_loss, pt->cos_loss_before);
#undef ACCUM_WEIGHT
/* Per primitive receiver MC accumulation */
@@ -595,10 +616,11 @@ update_mc
mc_prim->Name.weight += (W); \
mc_prim->Name.sqr_weight += (W)*(W); \
} (void)0
- ACCUM_WEIGHT(integrated_irradiance, pt->weight);
- ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss);
- ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss);
- ACCUM_WEIGHT(cos_loss, pt->cos_loss);
+ ACCUM_WEIGHT(integrated_irradiance, pt->incoming_weight);
+ ACCUM_WEIGHT(integrated_absorbed_irradiance, pt->absorbed_irradiance);
+ ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss_before);
+ ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss_before);
+ ACCUM_WEIGHT(cos_loss, pt->cos_loss_before);
#undef ACCUM_WEIGHT
}
@@ -651,13 +673,28 @@ trace_radiative_path
struct ray_data ray_data = RAY_DATA_NULL;
struct ssol_material* mtl;
+ /* Compute interaction with material */
+ mtl = point_get_material(&pt);
+ if(mtl->type == SSOL_MATERIAL_VIRTUAL) {
+ point_hit_virtual(&pt);
+ }
+ else {
+ /* Modulate the point weight wrt to its scattering functions and
+ * generate an outgoing direction */
+ res = point_shade(&pt, thread_ctx->bsdf, thread_ctx->rng, pt.dir);
+ if(res != RES_OK) goto error;
+ }
+
if(point_is_receiver(&pt)) {
hit_a_receiver = 1;
res = update_mc(&pt, path_id, depth, &thread_ctx->mc_rcvs, output);
if(res != RES_OK) goto error;
}
- mtl = point_get_material(&pt);
+ /* Stop the radiative random walk */
+ if(pt.weight == 0) break;
+
+ /* Setup new ray parameters */
if(mtl->type == SSOL_MATERIAL_VIRTUAL) {
/* Note that for Virtual materials, the ray parameters 'org' & 'dir'
* are not updated to ensure that it pursues its traversal without any
@@ -665,16 +702,6 @@ trace_radiative_path
range[0] = nextafterf(hit.distance, FLT_MAX);
range[1] = FLT_MAX;
} else {
-
- /* Modulate the point weight wrt to its scattering functions and
- * generate an outgoing direction */
- res = point_shade(&pt, thread_ctx->bsdf, thread_ctx->rng, pt.dir);
- if(res != RES_OK) goto error;
-
- /* Stop the radiative random walk */
- if(pt.weight == 0) break;
-
- /* Setup new ray parameters */
f2(range, 0, FLT_MAX);
f3_set_d3(org, pt.pos);
f3_set_d3(dir, pt.dir);
diff --git a/src/test_ssol_solver7.c b/src/test_ssol_solver7.c
@@ -24,7 +24,7 @@
#define HEIGHT 480
#define PROJ_RATIO (double)WIDTH/(double)HEIGHT
-#define REFLECTIVITY 0
+#define REFLECTIVITY 0.1
#include "test_ssol_materials.h"
#define TARGET_SZ 2
@@ -211,9 +211,13 @@ main(int argc, char** argv)
CHECK(eq_eps(mc_global.missing.E, 0, 1e-4), 1);
CHECK(GET_MC_RCV(estimator, target, SSOL_FRONT, &mc_rcv), RES_OK);
+ printf("Abs(target1) = %g +/- %g\n",
+ mc_rcv.integrated_absorbed_irradiance.E, mc_rcv.integrated_absorbed_irradiance.SE);
printf("Ir(target1) = %g +/- %g\n",
mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE);
CHECK(eq_eps(mc_rcv.integrated_irradiance.E, TOTAL, TOTAL * 1e-4), 1);
+ CHECK(eq_eps(mc_rcv.integrated_absorbed_irradiance.E,
+ (1 - REFLECTIVITY) * TOTAL, (1 - REFLECTIVITY) *TOTAL * 1e-4), 1);
CHECK(eq_eps(mc_rcv.integrated_irradiance.SE, 0, 1e-4), 1);
/* Free data */