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
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2017-09-15 02:55:44 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2017-09-20 20:38:08 +0300
commitb3afc8917cdeaa98ebfa3f2aa17e8c5a69fdb1e3 (patch)
treecb9839b83117967193fdfb4c89bd1fa421160f7e /intern
parentd029399e6b6d221766ccee49f4814f3b925d6ae8 (diff)
Code cleanup: refactor BSSRDF closure sampling, for next commit.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h2
-rw-r--r--intern/cycles/kernel/kernel_path.h6
-rw-r--r--intern/cycles/kernel/kernel_path_subsurface.h6
-rw-r--r--intern/cycles/kernel/kernel_shader.h113
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h122
-rw-r--r--intern/cycles/kernel/split/kernel_subsurface_scatter.h6
6 files changed, 115 insertions, 140 deletions
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 06221189060..267aeea6e86 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -400,7 +400,7 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
bssrdf_burley_setup(bssrdf);
}
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF;
+ return SD_BSSRDF;
}
}
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 2c79f5892e6..86b2aa00776 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -483,11 +483,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* bssrdf scatter to a different location on the same object, replacing
* the closures with a diffuse BSDF */
if(sd->flag & SD_BSSRDF) {
- float bssrdf_probability;
- ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
-
- /* modify throughput for picking bssrdf or bsdf */
- throughput *= bssrdf_probability;
+ const ShaderClosure *sc = shader_bssrdf_pick(sd, &throughput);
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h
index 619d57e71fb..cc6231eb6b1 100644
--- a/intern/cycles/kernel/kernel_path_subsurface.h
+++ b/intern/cycles/kernel/kernel_path_subsurface.h
@@ -32,11 +32,7 @@ bool kernel_path_subsurface_scatter(
ccl_addr_space float3 *throughput,
ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
{
- float bssrdf_probability;
- ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
-
- /* modify throughput for picking bssrdf or bsdf */
- *throughput *= bssrdf_probability;
+ const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput);
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 5964aca0c78..88aa1f712a4 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -497,17 +497,14 @@ ccl_device_inline void shader_merge_closures(ShaderData *sd)
/* BSDF */
ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, float *pdf,
- int skip_bsdf, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
+ const ShaderClosure *skip_sc, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
{
/* this is the veach one-sample model with balance heuristic, some pdf
* factors drop out when using balance heuristic weighting */
for(int i = 0; i < sd->num_closure; i++) {
- if(i == skip_bsdf)
- continue;
-
const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF(sc->type)) {
+ if(sc != skip_sc && CLOSURE_IS_BSDF(sc->type)) {
float bsdf_pdf = 0.0f;
float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
@@ -570,7 +567,7 @@ void shader_bsdf_eval(KernelGlobals *kg,
#endif
{
float pdf;
- _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, -1, eval, 0.0f, 0.0f);
+ _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, NULL, eval, 0.0f, 0.0f);
if(use_mis) {
float weight = power_heuristic(light_pdf, pdf);
bsdf_eval_mis(eval, weight);
@@ -578,48 +575,106 @@ void shader_bsdf_eval(KernelGlobals *kg,
}
}
-ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
- ShaderData *sd,
- float randu, float randv,
- BsdfEval *bsdf_eval,
- float3 *omega_in,
- differential3 *domega_in,
- float *pdf)
+ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd)
{
int sampled = 0;
if(sd->num_closure > 1) {
- /* pick a BSDF closure based on sample weights */
+ /* Pick a BSDF or based on sample weights. */
float sum = 0.0f;
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
-
- if(CLOSURE_IS_BSDF(sc->type))
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF(sc->type)) {
sum += sc->sample_weight;
+ }
}
float r = sd->randb_closure*sum;
- sum = 0.0f;
+ float partial_sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
-
if(CLOSURE_IS_BSDF(sc->type)) {
- sum += sc->sample_weight;
+ partial_sum += sc->sample_weight;
- if(r <= sum)
+ if(r <= partial_sum) {
+ sampled = i;
break;
+ }
}
}
+ }
- if(sampled == sd->num_closure) {
- *pdf = 0.0f;
- return LABEL_NONE;
+ return &sd->closure[sampled];
+}
+
+ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd,
+ ccl_addr_space float3 *throughput)
+{
+ int sampled = 0;
+
+ if(sd->num_closure > 1) {
+ /* Pick a BSDF or BSSRDF or based on sample weights. */
+ float sum_bsdf = 0.0f;
+ float sum_bssrdf = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ sum_bsdf += sc->sample_weight;
+ }
+ else if(CLOSURE_IS_BSSRDF(sc->type)) {
+ sum_bssrdf += sc->sample_weight;
+ }
+ }
+
+ float r = sd->randb_closure*(sum_bsdf + sum_bssrdf);
+ float partial_sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ partial_sum += sc->sample_weight;
+
+ if(r <= partial_sum) {
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ *throughput *= (sum_bsdf + sum_bssrdf) / sum_bsdf;
+ return NULL;
+ }
+ else {
+ *throughput *= (sum_bsdf + sum_bssrdf) / sum_bssrdf;
+ sampled = i;
+ break;
+ }
+ }
+ }
}
}
- const ShaderClosure *sc = &sd->closure[sampled];
+ return &sd->closure[sampled];
+}
+
+ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
+ ShaderData *sd,
+ float randu, float randv,
+ BsdfEval *bsdf_eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
+{
+ const ShaderClosure *sc = shader_bsdf_pick(sd);
+ if(!sc) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+
+ /* BSSRDF should already have been handled elsewhere. */
+ kernel_assert(CLOSURE_IS_BSDF(sc->type));
int label;
float3 eval;
@@ -632,7 +687,7 @@ ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
if(sd->num_closure > 1) {
float sweight = sc->sample_weight;
- _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
+ _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sc, bsdf_eval, *pdf*sweight, sweight);
}
}
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 26ec6383b73..027d59b5a4e 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -28,87 +28,31 @@ CCL_NAMESPACE_BEGIN
* - try to reduce one sample model variance
*/
-#define BSSRDF_MULTI_EVAL
-
-ccl_device ShaderClosure *subsurface_scatter_pick_closure(KernelGlobals *kg, ShaderData *sd, float *probability)
-{
- /* sum sample weights of bssrdf and bsdf */
- float bsdf_sum = 0.0f;
- float bssrdf_sum = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSDF(sc->type))
- bsdf_sum += sc->sample_weight;
- else if(CLOSURE_IS_BSSRDF(sc->type))
- bssrdf_sum += sc->sample_weight;
- }
-
- /* use bsdf or bssrdf? */
- float r = sd->randb_closure*(bsdf_sum + bssrdf_sum);
-
- if(r < bsdf_sum) {
- /* use bsdf, and adjust randb so we can reuse it for picking a bsdf */
- sd->randb_closure = r/bsdf_sum;
- *probability = (bsdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bsdf_sum: 1.0f;
- return NULL;
- }
-
- /* use bssrdf */
- r -= bsdf_sum;
-
- float sum = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSSRDF(sc->type)) {
- sum += sc->sample_weight;
-
- if(r <= sum) {
- sd->randb_closure = (r - (sum - sc->sample_weight))/sc->sample_weight;
-
-#ifdef BSSRDF_MULTI_EVAL
- *probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bssrdf_sum: 1.0f;
-#else
- *probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/sc->sample_weight: 1.0f;
-#endif
- return sc;
- }
- }
- }
-
- /* should never happen */
- sd->randb_closure = 0.0f;
- *probability = 1.0f;
- return NULL;
-}
-
ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd,
- ShaderClosure *sc,
+ const ShaderClosure *sc,
float disk_r,
float r,
bool all)
{
-#ifdef BSSRDF_MULTI_EVAL
/* this is the veach one-sample model with balance heuristic, some pdf
* factors drop out when using balance heuristic weighting */
float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
float pdf_sum = 0.0f;
- float sample_weight_sum = 0.0f;
- int num_bssrdf = 0;
+ float sample_weight_inv = 0.0f;
- for(int i = 0; i < sd->num_closure; i++) {
- sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSSRDF(sc->type)) {
- float sample_weight = (all)? 1.0f: sc->sample_weight;
- sample_weight_sum += sample_weight;
+ if(!all) {
+ float sample_weight_sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSSRDF(sc->type)) {
+ sample_weight_sum += sc->sample_weight;
+ }
}
- }
- float sample_weight_inv = 1.0f/sample_weight_sum;
+ sample_weight_inv = 1.0f/sample_weight_sum;
+ }
for(int i = 0; i < sd->num_closure; i++) {
sc = &sd->closure[i];
@@ -125,22 +69,14 @@ ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd,
/* TODO power heuristic is not working correct here */
eval_sum += sc->weight*pdf; //*sample_weight*disk_pdf;
pdf_sum += sample_weight*disk_pdf; //*sample_weight*disk_pdf;
-
- num_bssrdf++;
}
}
return (pdf_sum > 0.0f)? eval_sum / pdf_sum : make_float3(0.0f, 0.0f, 0.0f);
-#else
- float pdf = bssrdf_pdf(pick_sc, r);
- float disk_pdf = bssrdf_pdf(pick_sc, disk_r);
-
- return pick_sc->weight * pdf / disk_pdf;
-#endif
}
/* replace closures with a single diffuse bsdf closure after scatter step */
-ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, ShaderClosure *sc, float3 weight, bool hit, float3 N)
+ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, const ShaderClosure *sc, float3 weight, bool hit, float3 N)
{
sd->flag &= ~SD_CLOSURE_FLAGS;
sd->randb_closure = 0.0f;
@@ -242,7 +178,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
KernelGlobals *kg,
SubsurfaceIntersection *ss_isect,
ShaderData *sd,
- ShaderClosure *sc,
+ const ShaderClosure *sc,
uint *lcg_state,
float disk_u,
float disk_v,
@@ -255,26 +191,20 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
disk_N = sd->Ng;
make_orthonormals(disk_N, &disk_T, &disk_B);
- /* reusing variable for picking the closure gives a bit nicer stratification
- * for path tracer, for branched we do all closures so it doesn't help */
- float axisu = (all)? disk_u: sd->randb_closure;
-
- if(axisu < 0.5f) {
+ if(disk_u < 0.5f) {
pick_pdf_N = 0.5f;
pick_pdf_T = 0.25f;
pick_pdf_B = 0.25f;
- if(all)
- disk_u *= 2.0f;
+ disk_u *= 2.0f;
}
- else if(axisu < 0.75f) {
+ else if(disk_u < 0.75f) {
float3 tmp = disk_N;
disk_N = disk_T;
disk_T = tmp;
pick_pdf_N = 0.25f;
pick_pdf_T = 0.5f;
pick_pdf_B = 0.25f;
- if(all)
- disk_u = (disk_u - 0.5f)*4.0f;
+ disk_u = (disk_u - 0.5f)*4.0f;
}
else {
float3 tmp = disk_N;
@@ -283,8 +213,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
pick_pdf_N = 0.25f;
pick_pdf_T = 0.25f;
pick_pdf_B = 0.5f;
- if(all)
- disk_u = (disk_u - 0.75f)*4.0f;
+ disk_u = (disk_u - 0.75f)*4.0f;
}
/* sample point on disk */
@@ -390,7 +319,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
ShaderData *sd,
ccl_addr_space PathState *state,
int state_flag,
- ShaderClosure *sc,
+ const ShaderClosure *sc,
bool all)
{
#ifdef __SPLIT_KERNEL__
@@ -419,7 +348,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state,
- int state_flag, ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
+ int state_flag, const ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -430,18 +359,20 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_a
disk_N = sd->Ng;
make_orthonormals(disk_N, &disk_T, &disk_B);
- if(sd->randb_closure < 0.5f) {
+ if(disk_u < 0.5f) {
pick_pdf_N = 0.5f;
pick_pdf_T = 0.25f;
pick_pdf_B = 0.25f;
+ disk_u *= 2.0f;
}
- else if(sd->randb_closure < 0.75f) {
+ else if(disk_u < 0.75f) {
float3 tmp = disk_N;
disk_N = disk_T;
disk_T = tmp;
pick_pdf_N = 0.25f;
pick_pdf_T = 0.5f;
pick_pdf_B = 0.25f;
+ disk_u = (disk_u - 0.5f)*4.0f;
}
else {
float3 tmp = disk_N;
@@ -450,6 +381,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_a
pick_pdf_N = 0.25f;
pick_pdf_T = 0.25f;
pick_pdf_B = 0.5f;
+ disk_u = (disk_u - 0.75f)*4.0f;
}
/* sample point on disk */
diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
index a487e53df5c..6caa18518dd 100644
--- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h
+++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
@@ -250,11 +250,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
#ifdef __BRANCHED_PATH__
}
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
- float bssrdf_probability;
- ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
-
- /* modify throughput for picking bssrdf or bsdf */
- *throughput *= bssrdf_probability;
+ const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput);
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {