[Bf-blender-cvs] [c2cdb38] openvdb: Cycles: use vdb ray intersectors for shadow rays as well.

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


Commit: c2cdb38376d5cd85df1c93a8c8cc4d6fdb626ce7
Author: Kévin Dietrich
Date:   Tue Jun 9 01:54:55 2015 +0200
Branches: openvdb
https://developer.blender.org/rBc2cdb38376d5cd85df1c93a8c8cc4d6fdb626ce7

Cycles: use vdb ray intersectors for shadow rays as well.

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

M	intern/cycles/kernel/kernel_volume.h

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

diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 95ba043..9924a38 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -162,6 +162,38 @@ ccl_device void kernel_volume_shadow_homogeneous(KernelGlobals *kg, PathState *s
 		*throughput *= volume_color_transmittance(sigma_t, ray->t);
 }
 
+ccl_device_inline bool kernel_volume_integrate_shadow_ray(
+        KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd,
+        float3 *tp, float t, float new_t, float random_jitter_offset,
+        float3 *sum, float tp_eps, int i)
+{
+	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);
+	float3 sigma_t;
+
+	/* compute attenuation over segment */
+	if(volume_shader_extinction_sample(kg, sd, state, new_P, &sigma_t)) {
+		/* Compute expf() only for every Nth step, to save some calculations
+		 * because exp(a)*exp(b) = exp(a+b), also do a quick tp_eps check then. */
+
+		*sum += (-sigma_t * (new_t - t));
+		if((i & 0x07) == 0) { /* ToDo: Other interval? */
+			*tp = *tp * make_float3(expf(sum->x), expf(sum->y), expf(sum->z));
+
+			/* stop if nearly all light is blocked */
+			if(tp->x < tp_eps && tp->y < tp_eps && tp->z < tp_eps)
+				return true;
+		}
+	}
+
+	return false;
+}
+
 /* heterogeneous volume: integrate stepping through the volume until we
  * reach the end, get absorbed entirely, or run out of iterations */
 ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd, float3 *throughput)
@@ -179,42 +211,66 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
 
 	float3 sum = make_float3(0.0f, 0.0f, 0.0f);
 
-	for(int i = 0; i < max_steps; i++) {
-		/* advance to new position */
-		float new_t = min(ray->t, (i+1) * step);
-		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;
+#ifdef __OPENVDB__
+	int vdb_index = kernel_data.tables.density_index;
+	bool has_vdb_volume = kernel_data.tables.num_volumes > 0;
+	float t1 = 0.0f;
 
-		float3 new_P = ray->P + ray->D * (t + random_jitter_offset);
-		float3 sigma_t;
+	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
+		 * checking if we have an intersection with the boundbox of the volumue
+		 * which in most cases corresponds to the boundbox of the object that has
+		 * this volume. Also it initializes the rays for the ray marching. */
+		if(!kg->float_volumes[vdb_index]->intersect(ray, NULL)) {
+			return;
+		}
 
-		/* compute attenuation over segment */
-		if(volume_shader_extinction_sample(kg, sd, state, new_P, &sigma_t)) {
-			/* Compute expf() only for every Nth step, to save some calculations
-			 * because exp(a)*exp(b) = exp(a+b), also do a quick tp_eps check then. */
+		/* t and t1 represent the entry and exit points for each leaf node or tile
+		 * containing active voxels. If we don't have any active node in the current
+		 * ray path (i.e. empty space) the ray march loop is not executed,
+		 * otherwise we loop through all leaves until the end of the volume. */
+		while(kg->float_volumes[vdb_index]->march(&t, &t1)) {
+			int i = 0;
 
-			sum += (-sigma_t * (new_t - t));
-			if((i & 0x07) == 0) { /* ToDo: Other interval? */
-				tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
+			/* Perform small steps through the current leaf or tile. */
+			for(float new_t = step * ceilf(t / step); new_t <= t1; new_t += step) {
+				bool ok = kernel_volume_integrate_shadow_ray(
+				              kg, state, ray, sd, &tp, t, new_t, random_jitter_offset,
+				              &sum, tp_eps, i);
+
+				if (ok) {
+					*throughput = tp;
+					return;
+				}
 
-				/* stop if nearly all light is blocked */
-				if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
-					break;
+				/* stop if at the end of the volume */
+				t = new_t;
+				i++;
 			}
 		}
+	}
+	else
+#endif
+	{
+		for(int i = 0; i < max_steps; i++) {
+			/* advance to new position */
+			float new_t = min(ray->t, (i+1) * step);
 
-		/* stop if at the end of the volume */
-		t = new_t;
-		if(t == ray->t) {
-			/* Update throughput in case we haven't done it above */
-			tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
-			break;
+			bool ok = kernel_volume_integrate_shadow_ray(
+			              kg, state, ray, sd, &tp, t, new_t, random_jitter_offset,
+			              &sum, tp_eps, i);
+
+			/* stop if at the end of the volume */
+			t = new_t;
+			if(ok || t == ray->t) {
+				break;
+			}
 		}
 	}
 
+	/* Update throughput in case we haven't done it above */
+	tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
+
 	*throughput = tp;
 }




More information about the Bf-blender-cvs mailing list