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
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/kernel_volume.h')
-rw-r--r--intern/cycles/kernel/kernel_volume.h75
1 files changed, 37 insertions, 38 deletions
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index e46b0436107..22a89997683 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -175,7 +175,8 @@ ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg,
const float object_step_size,
float t,
float *step_size,
- float *step_offset)
+ float *step_shade_offset,
+ float *steps_offset)
{
const int max_steps = kernel_data.integrator.volume_max_steps;
float step = min(object_step_size, t);
@@ -186,7 +187,14 @@ ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg,
}
*step_size = step;
- *step_offset = path_state_rng_1D_hash(kg, state, 0x1e31d8a4) * step;
+
+ /* Perform shading at this offset within a step, to integrate over
+ * over the entire step segment. */
+ *step_shade_offset = path_state_rng_1D_hash(kg, state, 0x1e31d8a4);
+
+ /* Shift starting point of all segment by this random amount to avoid
+ * banding artifacts from the volume bounding shape. */
+ *steps_offset = path_state_rng_1D_hash(kg, state, 0x3d22c7b3);
}
/* Volume Shadows
@@ -220,10 +228,15 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
float3 tp = *throughput;
const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
- /* prepare for stepping */
+ /* Prepare for stepping.
+ * For shadows we do not offset all segments, since the starting point is
+ * already a random distance inside the volume. It also appears to create
+ * banding artifacts for unknown reasons. */
int max_steps = kernel_data.integrator.volume_max_steps;
- float step_offset, step_size;
- kernel_volume_step_init(kg, state, object_step_size, ray->t, &step_size, &step_offset);
+ float step_size, step_shade_offset, unused;
+ kernel_volume_step_init(
+ kg, state, object_step_size, ray->t, &step_size, &step_shade_offset, &unused);
+ const float steps_offset = 1.0f;
/* compute extinction at the start */
float t = 0.0f;
@@ -232,23 +245,17 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
for (int i = 0; i < max_steps; i++) {
/* advance to new position */
- float new_t = min(ray->t, (i + 1) * step_size);
-
- /* use random position inside this segment to sample shader, adjust
- * for last step that is shorter than other steps. */
- if (new_t == ray->t) {
- step_offset *= (new_t - t) / step_size;
- }
+ float new_t = min(ray->t, (i + steps_offset) * step_size);
+ float dt = new_t - t;
- float3 new_P = ray->P + ray->D * (t + step_offset);
+ float3 new_P = ray->P + ray->D * (t + dt * step_shade_offset);
float3 sigma_t = zero_float3();
/* 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));
+ sum += (-sigma_t * dt);
if ((i & 0x07) == 0) { /* ToDo: Other interval? */
tp = *throughput * exp3(sum);
@@ -567,10 +574,12 @@ kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
float3 tp = *throughput;
const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
- /* prepare for stepping */
+ /* Prepare for stepping.
+ * Using a different step offset for the first step avoids banding artifacts. */
int max_steps = kernel_data.integrator.volume_max_steps;
- float step_offset, step_size;
- kernel_volume_step_init(kg, state, object_step_size, ray->t, &step_size, &step_offset);
+ float step_size, step_shade_offset, steps_offset;
+ kernel_volume_step_init(
+ kg, state, object_step_size, ray->t, &step_size, &step_shade_offset, &steps_offset);
/* compute coefficients at the start */
float t = 0.0f;
@@ -584,16 +593,10 @@ kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
for (int i = 0; i < max_steps; i++) {
/* advance to new position */
- float new_t = min(ray->t, (i + 1) * step_size);
+ float new_t = min(ray->t, (i + steps_offset) * step_size);
float dt = new_t - t;
- /* use random position inside this segment to sample shader,
- * for last shorter step we remap it to fit within the segment. */
- if (new_t == ray->t) {
- step_offset *= (new_t - t) / step_size;
- }
-
- float3 new_P = ray->P + ray->D * (t + step_offset);
+ float3 new_P = ray->P + ray->D * (t + dt * step_shade_offset);
VolumeShaderCoefficients coeff ccl_optional_struct_init;
/* compute segment */
@@ -771,11 +774,12 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
/* prepare for volume stepping */
int max_steps;
- float step_size, step_offset;
+ float step_size, step_shade_offset, steps_offset;
if (object_step_size != FLT_MAX) {
max_steps = kernel_data.integrator.volume_max_steps;
- kernel_volume_step_init(kg, state, object_step_size, ray->t, &step_size, &step_offset);
+ kernel_volume_step_init(
+ kg, state, object_step_size, ray->t, &step_size, &step_shade_offset, &steps_offset);
# ifdef __KERNEL_CPU__
/* NOTE: For the branched path tracing it's possible to have direct
@@ -802,7 +806,8 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
else {
max_steps = 1;
step_size = ray->t;
- step_offset = 0.0f;
+ step_shade_offset = 0.0f;
+ steps_offset = 1.0f;
segment->steps = &segment->stack_step;
}
@@ -821,16 +826,10 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
for (int i = 0; i < max_steps; i++, step++) {
/* advance to new position */
- float new_t = min(ray->t, (i + 1) * step_size);
+ float new_t = min(ray->t, (i + steps_offset) * step_size);
float dt = new_t - t;
- /* use random position inside this segment to sample shader,
- * for last shorter step we remap it to fit within the segment. */
- if (new_t == ray->t) {
- step_offset *= (new_t - t) / step_size;
- }
-
- float3 new_P = ray->P + ray->D * (t + step_offset);
+ float3 new_P = ray->P + ray->D * (t + dt * step_shade_offset);
VolumeShaderCoefficients coeff ccl_optional_struct_init;
/* compute segment */
@@ -888,7 +887,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
step->accum_transmittance = accum_transmittance;
step->cdf_distance = cdf_distance;
step->t = new_t;
- step->shade_t = t + step_offset;
+ step->shade_t = t + dt * step_shade_offset;
/* stop if at the end of the volume */
t = new_t;