diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-02-04 17:25:29 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-02-04 17:29:58 +0300 |
commit | 3e7389eaf2d7ffbd180931c117776d3de2da5adb (patch) | |
tree | d63be65c92ad5b50e07f8e0425394d0add1aef62 /intern/cycles/kernel/closure/bssrdf.h | |
parent | f250aa9d86a35ae8bb6692a85ffe04610924fb08 (diff) |
Cycles: Speedup of Christensen-Burley SSS falloff function
The idea is simply to pre-compute fitting and parameterization
in the bssrdf_setup() function and re-use the values in both
sample() and eval().
The only trick is where to store the pre-calculated values and
the answer is inside of ShaderClosure->custom{1,2,3}. There's
no memory bump here because we now simply re-use padding fields
for the pre-calculated values. Similar trick we can do for other
BSDFs.
Seems to give nice speedup up to 7% here on my desktop with
Core i7 CPU, SSE4.1 kernel.
Diffstat (limited to 'intern/cycles/kernel/closure/bssrdf.h')
-rw-r--r-- | intern/cycles/kernel/closure/bssrdf.h | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index 041832ee5b7..522bc369618 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -19,25 +19,6 @@ CCL_NAMESPACE_BEGIN -ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) -{ - if(sc->data0 < BSSRDF_MIN_RADIUS) { - /* revert to diffuse BSDF if radius too small */ - sc->data0 = 0.0f; - sc->data1 = 0.0f; - int flag = bsdf_diffuse_setup(sc); - sc->type = CLOSURE_BSDF_BSSRDF_ID; - return flag; - } - else { - sc->data1 = saturate(sc->data1); /* texture blur */ - sc->T.x = saturate(sc->T.x); /* sharpness */ - sc->type = type; - - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF; - } -} - /* Planar Truncated Gaussian * * Note how this is different from the typical gaussian, this one integrates @@ -210,13 +191,24 @@ ccl_device_inline float bssrdf_burley_compatible_mfp(float r) return 0.5f * M_1_PI_F * r; } -ccl_device float bssrdf_burley_eval(ShaderClosure *sc, float r) +ccl_device void bssrdf_burley_setup(ShaderClosure *sc) { /* Mean free path length. */ const float l = bssrdf_burley_compatible_mfp(sc->data0); /* Surface albedo. */ const float A = sc->data2; const float s = bssrdf_burley_fitting(A); + const float d = l / s; + + sc->custom1 = l; + sc->custom2 = s; + sc->custom3 = d; +} + +ccl_device float bssrdf_burley_eval(ShaderClosure *sc, float r) +{ + const float l = sc->custom1, + s = sc->custom2; /* Burley refletance profile, equation (3). * * Note that surface albedo is already included into sc->weight, no need to @@ -277,12 +269,7 @@ ccl_device void bssrdf_burley_sample(ShaderClosure *sc, float *r, float *h) { - /* Mean free path length. */ - const float l = bssrdf_burley_compatible_mfp(sc->data0); - /* Surface albedo. */ - const float A = sc->data2; - const float s = bssrdf_burley_fitting(A); - const float d = l / s; + const float d = sc->custom3; /* This is a bit arbitrary, just need big enough radius so it matches * the mean free length, but still not too big so sampling is still * effective. Might need some further tweaks. @@ -330,6 +317,29 @@ ccl_device void bssrdf_none_sample(ShaderClosure *sc, float xi, float *r, float /* Generic */ +ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) +{ + if(sc->data0 < BSSRDF_MIN_RADIUS) { + /* revert to diffuse BSDF if radius too small */ + sc->data0 = 0.0f; + sc->data1 = 0.0f; + int flag = bsdf_diffuse_setup(sc); + sc->type = CLOSURE_BSDF_BSSRDF_ID; + return flag; + } + else { + sc->data1 = saturate(sc->data1); /* texture blur */ + sc->T.x = saturate(sc->T.x); /* sharpness */ + sc->type = type; + + if(type == CLOSURE_BSSRDF_BURLEY_ID) { + bssrdf_burley_setup(sc); + } + + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF; + } +} + ccl_device void bssrdf_sample(ShaderClosure *sc, float xi, float *r, float *h) { if(sc->type == CLOSURE_BSSRDF_CUBIC_ID) |