[Bf-blender-cvs] [2d81758aa65] master: Cycles: better path termination for transparency.

Brecht Van Lommel noreply at git.blender.org
Thu Feb 22 00:58:56 CET 2018


Commit: 2d81758aa650256d6b6ed283e43b6c35808ed205
Author: Brecht Van Lommel
Date:   Tue Feb 20 14:22:40 2018 +0100
Branches: master
https://developer.blender.org/rB2d81758aa650256d6b6ed283e43b6c35808ed205

Cycles: better path termination for transparency.

We now continue transparent paths after diffuse/glossy/transmission/volume
bounces are exceeded. This avoids unexpected boundaries in volumes with
transparent boundaries. It is also required for MIS to work correctly with
transparent surfaces, as we also continue through these in shadow rays.

The main visible changes is that volumes will now be lit by the background
even at volume bounces 0, same as surfaces.

Fixes T53914 and T54103.

===================================================================

M	intern/cycles/kernel/closure/bsdf_transparent.h
M	intern/cycles/kernel/kernel_bake.h
M	intern/cycles/kernel/kernel_emission.h
M	intern/cycles/kernel/kernel_path.h
M	intern/cycles/kernel/kernel_path_branched.h
M	intern/cycles/kernel/kernel_path_state.h
M	intern/cycles/kernel/kernel_shader.h
M	intern/cycles/kernel/kernel_shadow.h
M	intern/cycles/kernel/kernel_subsurface.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/kernel/osl/osl_closures.cpp
M	intern/cycles/kernel/split/kernel_shader_eval.h
M	intern/cycles/kernel/svm/svm_closure.h
M	intern/cycles/render/osl.cpp

===================================================================

diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h
index 22ca7f3847e..79ee9dc4537 100644
--- a/intern/cycles/kernel/closure/bsdf_transparent.h
+++ b/intern/cycles/kernel/closure/bsdf_transparent.h
@@ -35,21 +35,38 @@
 
 CCL_NAMESPACE_BEGIN
 
-ccl_device void bsdf_transparent_setup(ShaderData *sd, const float3 weight)
+ccl_device void bsdf_transparent_setup(ShaderData *sd, const float3 weight, int path_flag)
 {
 	if(sd->flag & SD_TRANSPARENT) {
 		sd->closure_transparent_extinction += weight;
+
+		for(int i = 0; i < sd->num_closure; i++) {
+			ShaderClosure *sc = &sd->closure[i];
+
+			if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
+				sc->weight += weight;
+				sc->sample_weight += fabsf(average(weight));
+				break;
+			}
+		}
 	}
 	else {
 		sd->flag |= SD_BSDF|SD_TRANSPARENT;
 		sd->closure_transparent_extinction = weight;
-	}
 
-	ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
+		if(path_flag & PATH_RAY_TERMINATE) {
+			/* In this case the number of closures is set to zero to disable
+			 * all others, but we still want to get transparency so increase
+			 * the number just for this. */
+			sd->num_closure_left = 1;
+		}
+
+		ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
 
-	if(bsdf) {
-		bsdf->N = sd->N;
-		bsdf->type = CLOSURE_BSDF_TRANSPARENT_ID;
+		if(bsdf) {
+			bsdf->N = sd->N;
+			bsdf->type = CLOSURE_BSDF_TRANSPARENT_ID;
+		}
 	}
 }
 
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 8788e89c40e..b3c2450d10e 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -51,7 +51,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
 	path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
 
 	/* evaluate surface shader */
-	shader_eval_surface(kg, sd, &state, state.flag, kernel_data.integrator.max_closures);
+	shader_eval_surface(kg, sd, &state, state.flag);
 
 	/* TODO, disable more closures we don't need besides transparent */
 	shader_bsdf_disable_transparency(kg, sd);
@@ -228,12 +228,12 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
 		}
 		else {
 			/* surface color of the pass only */
-			shader_eval_surface(kg, sd, state, 0, kernel_data.integrator.max_closures);
+			shader_eval_surface(kg, sd, state, 0);
 			return kernel_bake_shader_bsdf(kg, sd, type);
 		}
 	}
 	else {
-		shader_eval_surface(kg, sd, state, 0, kernel_data.integrator.max_closures);
+		shader_eval_surface(kg, sd, state, 0);
 		color = kernel_bake_shader_bsdf(kg, sd, type);
 	}
 
@@ -333,7 +333,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
 		{
 			float3 N = sd.N;
 			if((sd.flag & SD_HAS_BUMP)) {
-				shader_eval_surface(kg, &sd, &state, 0, kernel_data.integrator.max_closures);
+				shader_eval_surface(kg, &sd, &state, 0);
 				N = shader_bsdf_average_normal(kg, &sd);
 			}
 
@@ -348,7 +348,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
 		}
 		case SHADER_EVAL_EMISSION:
 		{
-			shader_eval_surface(kg, &sd, &state, 0, 0);
+			shader_eval_surface(kg, &sd, &state, PATH_RAY_EMISSION);
 			out = shader_emissive_eval(kg, &sd);
 			break;
 		}
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 94b0a37ce62..5875249b404 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -67,13 +67,13 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
 
 		ls->Ng = emission_sd->Ng;
 
-		/* no path flag, we're evaluating this for all closures. that's weak but
-		 * we'd have to do multiple evaluations otherwise */
+		/* No proper path flag, we're evaluating this for all closures. that's
+		 * weak but we'd have to do multiple evaluations otherwise. */
 		path_state_modify_bounce(state, true);
-		shader_eval_surface(kg, emission_sd, state, 0, 0);
+		shader_eval_surface(kg, emission_sd, state, PATH_RAY_EMISSION);
 		path_state_modify_bounce(state, false);
 
-		/* evaluate emissive closure */
+		/* Evaluate emissive closure. */
 		eval = shader_emissive_eval(kg, emission_sd);
 	}
 	
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 4728a25a3bc..aef350b0658 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -446,11 +446,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 		}
 
 		/* Setup and evaluate shader. */
-		shader_setup_from_ray(kg,
-		                      sd,
-		                      &isect,
-		                      ray);
-		shader_eval_surface(kg, sd, state, state->flag, kernel_data.integrator.max_closures);
+		shader_setup_from_ray(kg, sd, &isect, ray);
+		shader_eval_surface(kg, sd, state, state->flag);
 		shader_prepare_closures(sd, state);
 
 		/* Apply shadow catcher, holdout, emission. */
@@ -610,7 +607,7 @@ ccl_device_forceinline void kernel_path_integrate(
 
 		/* Setup and evaluate shader. */
 		shader_setup_from_ray(kg, &sd, &isect, ray);
-		shader_eval_surface(kg, &sd, state, state->flag, kernel_data.integrator.max_closures);
+		shader_eval_surface(kg, &sd, state, state->flag);
 		shader_prepare_closures(&sd, state);
 
 		/* Apply shadow catcher, holdout, emission. */
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index 6fb55bda08d..441a06eeba3 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -480,7 +480,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 
 		/* Setup and evaluate shader. */
 		shader_setup_from_ray(kg, &sd, &isect, &ray);
-		shader_eval_surface(kg, &sd, &state, state.flag, kernel_data.integrator.max_closures);
+		shader_eval_surface(kg, &sd, &state, state.flag);
 		shader_merge_closures(&sd);
 
 		/* Apply shadow catcher, holdout, emission. */
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index a16c20cbee6..15d81fcddf4 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -75,6 +75,9 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
 	if(label & LABEL_TRANSPARENT) {
 		state->flag |= PATH_RAY_TRANSPARENT;
 		state->transparent_bounce++;
+		if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
+			state->flag |= PATH_RAY_TERMINATE_IMMEDIATE;
+		}
 
 		if(!kernel_data.integrator.transparent_shadows)
 			state->flag |= PATH_RAY_MIS_SKIP;
@@ -86,6 +89,10 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
 	}
 
 	state->bounce++;
+	if(state->bounce >= kernel_data.integrator.max_bounce) {
+		state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+	}
+
 	state->flag &= ~(PATH_RAY_ALL_VISIBILITY|PATH_RAY_MIS_SKIP);
 
 #ifdef __VOLUME__
@@ -95,6 +102,9 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
 		state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
 
 		state->volume_bounce++;
+		if(state->volume_bounce >= kernel_data.integrator.max_volume_bounce) {
+			state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+		}
 	}
 	else
 #endif
@@ -104,10 +114,18 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
 			state->flag |= PATH_RAY_REFLECT;
 			state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
 
-			if(label & LABEL_DIFFUSE)
+			if(label & LABEL_DIFFUSE) {
 				state->diffuse_bounce++;
-			else
+				if(state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) {
+					state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+				}
+			}
+			else {
 				state->glossy_bounce++;
+				if(state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) {
+					state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+				}
+			}
 		}
 		else {
 			kernel_assert(label & LABEL_TRANSMIT);
@@ -119,6 +137,9 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
 			}
 
 			state->transmission_bounce++;
+			if(state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce) {
+				state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+			}
 		}
 
 		/* diffuse/glossy/singular */
@@ -162,13 +183,13 @@ ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg,
                                                             ccl_addr_space PathState *state,
                                                             const float3 throughput)
 {
-	if(state->flag & PATH_RAY_TRANSPARENT) {
-		/* Transparent rays are treated separately with own max bounces. */
-		if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
-			return 0.0f;
-		}
+	if(state->flag & PATH_RAY_TERMINATE_IMMEDIATE) {
+		/* Ray is to be terminated immediately. */
+		return 0.0f;
+	}
+	else if(state->flag & PATH_RAY_TRANSPARENT) {
 		/* Do at least one bounce without RR. */
-		else if(state->transparent_bounce <= 1) {
+		if(state->transparent_bounce <= 1) {
 			return 1.0f;
 		}
 #ifdef __SHADOW_TRICKS__
@@ -179,19 +200,8 @@ ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg,
 #endif
 	}
 	else {
-		/* Test max bounces for various ray types. */
-		if((state->bounce >= kernel_data.integrator.max_bounce) ||
-		   (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) ||
-		   (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) ||
-#ifdef __VOLUME__
-		   (state->volume_bounce >= kernel_data.integrator.max_volume_bounce) ||
-#endif
-		   (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce))
-		{
-			return 0.0f;
-		}
 		/* Do at least one bounce without RR. */
-		else if(state->bounce <= 1) {
+		if(state->bounce <= 1) {
 			return 1.0f;
 		}
 #ifdef __SHADOW_TRICKS__
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 5f2f00c5ceb..8cfd33b808e 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -966,10 +966,21 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list