[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