Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2018-01-27 00:11:28 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-01-27 01:06:53 +0300
commit7b29e917118ffdeb39de5c942dd652d40914dbc3 (patch)
tree55b5f0cc45cf07ef2cc72d26b8ca9f4fa7c07b8c /intern/cycles/kernel/closure
parentd611cf9233583a04b9168850ddbf708236de44b3 (diff)
Code refactor: make mixed small/large BSSRDF radii more robust.
Diffstat (limited to 'intern/cycles/kernel/closure')
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h108
1 files changed, 76 insertions, 32 deletions
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 383c168463b..c8f505e8418 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -27,6 +27,7 @@ typedef ccl_addr_space struct Bssrdf {
float sharpness;
float texture_blur;
float roughness;
+ float channels;
} Bssrdf;
/* Planar Truncated Gaussian
@@ -343,42 +344,68 @@ ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight)
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
}
-ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
+ccl_device int bssrdf_setup(ShaderData *sd, Bssrdf *bssrdf, ClosureType type)
{
- if(max3(bssrdf->radius) < BSSRDF_MIN_RADIUS) {
- /* revert to diffuse BSDF if radius too small */
- int flag;
+ int flag = 0;
+ int bssrdf_channels = 3;
+ float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f);
+
+ /* Verify if the radii are large enough to sample without precision issues. */
+ if(bssrdf->radius.x < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.x = bssrdf->weight.x;
+ bssrdf->weight.x = 0.0f;
+ bssrdf->radius.x = 0.0f;
+ bssrdf_channels--;
+ }
+ if(bssrdf->radius.y < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.y = bssrdf->weight.y;
+ bssrdf->weight.y = 0.0f;
+ bssrdf->radius.y = 0.0f;
+ bssrdf_channels--;
+ }
+ if(bssrdf->radius.z < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.z = bssrdf->weight.z;
+ bssrdf->weight.z = 0.0f;
+ bssrdf->radius.z = 0.0f;
+ bssrdf_channels--;
+ }
+
+ if(bssrdf_channels < 3) {
+ /* Add diffuse BSDF if any radius too small. */
#ifdef __PRINCIPLED__
if(type == CLOSURE_BSSRDF_PRINCIPLED_ID) {
float roughness = bssrdf->roughness;
float3 N = bssrdf->N;
- float3 weight = bssrdf->weight;
- float sample_weight = bssrdf->sample_weight;
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bssrdf;
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight);
- bsdf->N = N;
- bsdf->roughness = roughness;
- bsdf->weight = weight;
- bsdf->sample_weight = sample_weight;
- flag = bsdf_principled_diffuse_setup(bsdf);
- bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+ if(bsdf) {
+ bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+ flag |= bsdf_principled_diffuse_setup(bsdf);
+ }
}
else
#endif /* __PRINCIPLED__ */
{
- DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
- bsdf->N = bssrdf->N;
- flag = bsdf_diffuse_setup(bsdf);
- bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+ DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), diffuse_weight);
+
+ if(bsdf) {
+ bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+ bsdf->N = bssrdf->N;
+ flag |= bsdf_diffuse_setup(bsdf);
+ }
}
-
- return flag;
}
- else {
+
+ /* Setup BSSRDF if radius is large enough. */
+ if(bssrdf_channels > 0) {
+ bssrdf->type = type;
+ bssrdf->channels = bssrdf_channels;
+ bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf->channels;
bssrdf->texture_blur = saturate(bssrdf->texture_blur);
bssrdf->sharpness = saturate(bssrdf->sharpness);
- bssrdf->type = type;
if(type == CLOSURE_BSSRDF_BURLEY_ID ||
type == CLOSURE_BSSRDF_PRINCIPLED_ID)
@@ -386,8 +413,14 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
bssrdf_burley_setup(bssrdf);
}
- return SD_BSSRDF;
+ flag |= SD_BSSRDF;
}
+ else {
+ bssrdf->type = type;
+ bssrdf->sample_weight = 0.0f;
+ }
+
+ return flag;
}
ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float *h)
@@ -395,17 +428,22 @@ ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float
const Bssrdf *bssrdf = (const Bssrdf*)sc;
float radius;
- /* Sample color channel and reuse random number. */
- if(xi < 1.0f/3.0f) {
- xi *= 3.0f;
- radius = bssrdf->radius.x;
+ /* Sample color channel and reuse random number. Only a subset of channels
+ * may be used if their radius was too small to handle as BSSRDF. */
+ xi *= bssrdf->channels;
+
+ if(xi < 1.0f) {
+ radius = (bssrdf->radius.x > 0.0f)? bssrdf->radius.x:
+ (bssrdf->radius.y > 0.0f)? bssrdf->radius.y:
+ bssrdf->radius.z;
}
- else if(xi < 2.0f/3.0f) {
- xi = (xi - 1.0f/3.0f)*3.0f;
- radius = bssrdf->radius.y;
+ else if(xi < 2.0f) {
+ xi -= 1.0f;
+ radius = (bssrdf->radius.x > 0.0f)? bssrdf->radius.y:
+ bssrdf->radius.z;
}
else {
- xi = (xi - 2.0f/3.0f)*3.0f;
+ xi -= 2.0f;
radius = bssrdf->radius.z;
}
@@ -423,7 +461,10 @@ ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float
ccl_device float bssrdf_channel_pdf(const Bssrdf *bssrdf, float radius, float r)
{
- if(bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
+ if(radius == 0.0f) {
+ return 0.0f;
+ }
+ else if(bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
return bssrdf_cubic_pdf(radius, bssrdf->sharpness, r);
}
else if(bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
@@ -446,7 +487,10 @@ ccl_device_forceinline float3 bssrdf_eval(const ShaderClosure *sc, float r)
ccl_device_forceinline float bssrdf_pdf(const ShaderClosure *sc, float r)
{
- return average(bssrdf_eval(sc, r));
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ float3 pdf = bssrdf_eval(sc, r);
+
+ return (pdf.x + pdf.y + pdf.z) / bssrdf->channels;
}
CCL_NAMESPACE_END