[Bf-blender-cvs] [5cb2c01] openvdb: Cycles: de-duplicate ray march loops.

Kévin Dietrich noreply at git.blender.org
Tue Jun 9 02:02:52 CEST 2015


Commit: 5cb2c01ca576569b659229fbd0be9ee7b7268f72
Author: Kévin Dietrich
Date:   Sun Jun 7 19:50:02 2015 +0200
Branches: openvdb
https://developer.blender.org/rB5cb2c01ca576569b659229fbd0be9ee7b7268f72

Cycles: de-duplicate ray march loops.

The main logic was split up in a separate function which has quite a
number of arguments, could be worth looking into that matter at some
point. Also it seems like dense volume are slower to render now.

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

M	intern/cycles/kernel/kernel_volume.h

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

diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 8b84f8d..95ba043 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -21,7 +21,8 @@ CCL_NAMESPACE_BEGIN
 typedef enum VolumeIntegrateResult {
 	VOLUME_PATH_SCATTERED = 0,
 	VOLUME_PATH_ATTENUATED = 1,
-	VOLUME_PATH_MISSED = 2
+	VOLUME_PATH_MISSED = 2,
+	VOLUME_PATH_CONTINUE = 3,
 } VolumeIntegrateResult;
 
 /* Volume shader properties
@@ -420,6 +421,112 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 	return VOLUME_PATH_ATTENUATED;
 }
 
+ccl_device_inline VolumeIntegrateResult kernel_volume_integrate_ray(
+        KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd,
+        PathRadiance *L, float3 *throughput, float t, float new_t,
+        float random_jitter_offset, bool has_scatter, float3 *accum_transmittance,
+        int channel, const float tp_eps, float *xi)
+{
+	float dt = new_t - t;
+	float3 tp = *throughput;
+
+	/* use random position inside this segment to sample shader */
+	if(new_t == ray->t)
+		random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt;
+
+	float3 new_P = ray->P + ray->D * (t + random_jitter_offset);
+	VolumeShaderCoefficients coeff;
+
+	/* compute segment */
+	if(volume_shader_sample(kg, sd, state, new_P, &coeff)) {
+		int closure_flag = sd->flag;
+		float3 new_tp;
+		float3 transmittance;
+		bool scatter = false;
+
+		/* distance sampling */
+#ifdef __VOLUME_SCATTER__
+		if((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_ABSORPTION))) {
+			has_scatter = true;
+
+			float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
+			float3 sigma_s = coeff.sigma_s;
+
+			/* compute transmittance over full step */
+			transmittance = volume_color_transmittance(sigma_t, dt);
+
+			/* decide if we will scatter or continue */
+			float sample_transmittance = kernel_volume_channel_get(transmittance, channel);
+
+			if(1.0f - *xi >= sample_transmittance) {
+				/* compute sampling distance */
+				float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+				float new_dt = -logf(1.0f - *xi)/sample_sigma_t;
+				new_t = t + new_dt;
+
+				/* transmittance and pdf */
+				float3 new_transmittance = volume_color_transmittance(sigma_t, new_dt);
+				float3 pdf = sigma_t * new_transmittance;
+
+				/* throughput */
+				new_tp = tp * sigma_s * new_transmittance / average(pdf);
+				scatter = true;
+			}
+			else {
+				/* throughput */
+				float pdf = average(transmittance);
+				new_tp = tp * transmittance / pdf;
+
+				/* remap xi so we can reuse it and keep thing stratified */
+				*xi = 1.0f - (1.0f - *xi)/sample_transmittance;
+			}
+		}
+		else
+#endif
+			if(closure_flag & SD_ABSORPTION) {
+				/* absorption only, no sampling needed */
+				float3 sigma_a = coeff.sigma_a;
+
+				transmittance = volume_color_transmittance(sigma_a, dt);
+				new_tp = tp * transmittance;
+			}
+
+		/* integrate emission attenuated by absorption */
+		if(L && (closure_flag & SD_EMISSION)) {
+			float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt);
+			path_radiance_accum_emission(L, tp, emission, state->bounce);
+		}
+
+		/* modify throughput */
+		if(closure_flag & (SD_ABSORPTION|SD_SCATTER)) {
+			tp = new_tp;
+
+			/* stop if nearly all light blocked */
+			if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps) {
+				tp = make_float3(0.0f, 0.0f, 0.0f);
+				*throughput = tp;
+				return VOLUME_PATH_ATTENUATED;
+			}
+		}
+
+		/* prepare to scatter to new direction */
+		if(scatter) {
+			/* adjust throughput and move to new location */
+			sd->P = ray->P + new_t*ray->D;
+			*throughput = tp;
+
+			return VOLUME_PATH_SCATTERED;
+		}
+		else {
+			/* accumulate transmittance */
+			*accum_transmittance *= transmittance;
+		}
+	}
+
+	*throughput = tp;
+	return VOLUME_PATH_CONTINUE;
+}
+
 /* heterogeneous volume distance sampling: integrate stepping through the
  * volume until we reach the end, get absorbed entirely, or run out of
  * iterations. this does probalistically scatter or get transmitted through
@@ -427,7 +534,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
 	PathState *state, Ray *ray, ShaderData *sd, PathRadiance *L, float3 *throughput, RNG *rng)
 {
-	float3 tp = *throughput;
+	VolumeIntegrateResult result = VOLUME_PATH_MISSED;
 	const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
 
 	/* prepare for stepping */
@@ -446,9 +553,11 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
 	int channel = (int)(rphase*3.0f);
 	sd->randb_closure = rphase*3.0f - channel;
 	bool has_scatter = false;
+	bool path_missed = true;
+
+#ifdef __OPENVDB__
 	int vdb_index = kernel_data.tables.density_index;
 	bool has_vdb_volume = kernel_data.tables.num_volumes > 0;
-	bool path_missed = true;
 
 	if(has_vdb_volume && kg->float_volumes[vdb_index]->has_uniform_voxels()) {
 		/* TODO(kevin): this call should be moved out of here, all it does is
@@ -468,201 +577,32 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
 
 			/* Perform small steps through the current leaf or tile. */
 			for(float new_t = step_size * ceilf(t / step_size); new_t <= t1; new_t += step_size) {
-				float dt = new_t - t;
+				result = kernel_volume_integrate_ray(kg, state, ray, sd, L, throughput, t, new_t,
+				                                     random_jitter_offset, has_scatter,
+				                                     &accum_transmittance, channel, tp_eps, &xi);
 
-				/* use random position inside this segment to sample shader */
-				if(new_t == ray->t)
-					random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt;
-
-				float3 new_P = ray->P + ray->D * (t + random_jitter_offset);
-				VolumeShaderCoefficients coeff;
-
-				/* compute segment */
-				if(volume_shader_sample(kg, sd, state, new_P, &coeff)) {
-					int closure_flag = sd->flag;
-					float3 new_tp;
-					float3 transmittance;
-					bool scatter = false;
-
-					/* distance sampling */
-#ifdef __VOLUME_SCATTER__
-					if((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_ABSORPTION))) {
-						has_scatter = true;
-
-						float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
-						float3 sigma_s = coeff.sigma_s;
-
-						/* compute transmittance over full step */
-						transmittance = volume_color_transmittance(sigma_t, dt);
-
-						/* decide if we will scatter or continue */
-						float sample_transmittance = kernel_volume_channel_get(transmittance, channel);
-
-						if(1.0f - xi >= sample_transmittance) {
-							/* compute sampling distance */
-							float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
-							float new_dt = -logf(1.0f - xi)/sample_sigma_t;
-							new_t = t + new_dt;
-
-							/* transmittance and pdf */
-							float3 new_transmittance = volume_color_transmittance(sigma_t, new_dt);
-							float3 pdf = sigma_t * new_transmittance;
-
-							/* throughput */
-							new_tp = tp * sigma_s * new_transmittance / average(pdf);
-							scatter = true;
-						}
-						else {
-							/* throughput */
-							float pdf = average(transmittance);
-							new_tp = tp * transmittance / pdf;
-
-							/* remap xi so we can reuse it and keep thing stratified */
-							xi = 1.0f - (1.0f - xi)/sample_transmittance;
-						}
-					}
-					else
-#endif
-						if(closure_flag & SD_ABSORPTION) {
-							/* absorption only, no sampling needed */
-							float3 sigma_a = coeff.sigma_a;
-
-							transmittance = volume_color_transmittance(sigma_a, dt);
-							new_tp = tp * transmittance;
-						}
-
-					/* integrate emission attenuated by absorption */
-					if(L && (closure_flag & SD_EMISSION)) {
-						float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt);
-						path_radiance_accum_emission(L, tp, emission, state->bounce);
-					}
-
-					/* modify throughput */
-					if(closure_flag & (SD_ABSORPTION|SD_SCATTER)) {
-						tp = new_tp;
-
-						/* stop if nearly all light blocked */
-						if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps) {
-							tp = make_float3(0.0f, 0.0f, 0.0f);
-							break;
-						}
-					}
-
-					/* prepare to scatter to new direction */
-					if(scatter) {
-						/* adjust throughput and move to new location */
-						sd->P = ray->P + new_t*ray->D;
-						*throughput = tp;
-
-						return VOLUME_PATH_SCATTERED;
-					}
-					else {
-						/* accumulate transmittance */
-						accum_transmittance *= transmittance;
-					}
-				}
+				if(result != VOLUME_PATH_CONTINUE)
+					return result;
 
 				t = new_t;
 			}
 		}
 	}
-	else {
-		for (int i = 0; i < max_steps; i++) {
+	else
+#endif
+	{
+		path_missed = false;
+
+		for(int i = 0; i < max_steps; i++) {
 			/* advance to new position */
 			float new_t = min(ray->t, (i+1) * step_size);
-			float dt = new_t - t;
-
-			/* use random position inside this segment to sample shader */
-			if(new_t == ray->t)
-				random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt;
-
-			float3 new_P = ray->P + ray->D * (t + random_jitter_offset);
-			VolumeShaderCoefficients coeff;
-
-			/* compute segment */
-			if(volume_shader_sample(kg, sd, state, new_P, &coeff)) {
-				int closure_flag = sd->flag;
-				float3 new_tp;
-				float3 transmittance;
-				bool scatter = false;
-
-				/* distance sampling */
-		#ifdef __VOLUME_SCATTER__
-				if((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_ABSORPTION))) {
-					has_scatter = true;
 
-					float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
-					float3 sigma_s = coeff.sigma_s;
+			result = kernel_volume_integrate_ray(kg, state, ray, sd, L, throughput, t, new_t,
+			                                     random_jitter_offset, has_scatter,
+			                                     &accum_transmittance, channel, tp_eps, &xi);
 
-					/* compute transmittance over full step */
-					transmittance = volume_color_transmittance(sigma_t, dt);
-
-					/* decide if we will scatter or continue */
-					float sample_transmittance = kern

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list