diff options
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/kernel_path_state.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_random.h | 13 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 81 |
4 files changed, 61 insertions, 36 deletions
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 90937dbf86e..479bb22d780 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -60,8 +60,6 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, if(kernel_data.integrator.use_volumes) { /* Initialize volume stack with volume we are inside of. */ kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack); - /* Seed RNG for cases where we can't use stratified samples .*/ - state->rng_congruential = lcg_init(rng_hash + sample*0x51633e2d); } else { state->volume_stack[0].shader = SHADER_NONE; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index efb9048beb8..93152e9ff1c 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -199,6 +199,19 @@ ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, fx, fy); } +ccl_device_inline float path_state_rng_1D_hash(KernelGlobals *kg, + const ccl_addr_space PathState *state, + uint hash) +{ + /* Use a hash instead of dimension, this is not great but avoids adding + * more dimensions to each bounce which reduces quality of dimensions we + * are already using. */ + return path_rng_1D(kg, + cmj_hash_simple(state->rng_hash, hash), + state->sample, state->num_samples, + state->rng_offset); +} + ccl_device_inline float path_branched_rng_1D( KernelGlobals *kg, uint rng_hash, diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 2945cdb4593..af1ecb05788 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1107,7 +1107,6 @@ typedef struct PathState { #ifdef __VOLUME__ int volume_bounce; int volume_bounds_bounce; - uint rng_congruential; VolumeStack volume_stack[VOLUME_STACK_SIZE]; #endif } PathState; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 88360e5f1ae..86378289b02 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -156,6 +156,24 @@ ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stac return method; } +ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg, + ccl_addr_space PathState *state, + float t, + float *step_size, + float *step_offset) +{ + const int max_steps = kernel_data.integrator.volume_max_steps; + float step = min(kernel_data.integrator.volume_step_size, t); + + /* compute exact steps in advance for malloc */ + if(t > max_steps * step) { + step = t / (float)max_steps; + } + + *step_size = step; + *step_offset = path_state_rng_1D_hash(kg, state, 0x1e31d8a4) * step; +} + /* Volume Shadows * * These functions are used to attenuate shadow rays to lights. Both absorption @@ -188,8 +206,8 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, /* prepare for stepping */ int max_steps = kernel_data.integrator.volume_max_steps; - float step = kernel_data.integrator.volume_step_size; - float random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * step; + float step_offset, step_size; + kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); /* compute extinction at the start */ float t = 0.0f; @@ -198,14 +216,15 @@ 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); - float dt = new_t - t; + float new_t = min(ray->t, (i+1) * step_size); - /* use random position inside this segment to sample shader */ - if(new_t == ray->t) - random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * dt; + /* 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; + } - float3 new_P = ray->P + ray->D * (t + random_jitter_offset); + float3 new_P = ray->P + ray->D * (t + step_offset); float3 sigma_t; /* compute attenuation over segment */ @@ -504,8 +523,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance( /* prepare for stepping */ int max_steps = kernel_data.integrator.volume_max_steps; - float step_size = kernel_data.integrator.volume_step_size; - float random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * step_size; + float step_offset, step_size; + kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); /* compute coefficients at the start */ float t = 0.0f; @@ -522,11 +541,13 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance( 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_addrspace(&state->rng_congruential) * dt; + /* 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 + random_jitter_offset); + float3 new_P = ray->P + ray->D * (t + step_offset); VolumeShaderCoefficients coeff; /* compute segment */ @@ -694,19 +715,12 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta /* prepare for volume stepping */ int max_steps; - float step_size, random_jitter_offset; + float step_size, step_offset; if(heterogeneous) { - const int global_max_steps = kernel_data.integrator.volume_max_steps; - step_size = kernel_data.integrator.volume_step_size; - /* compute exact steps in advance for malloc */ - if(ray->t > global_max_steps*step_size) { - max_steps = global_max_steps; - step_size = ray->t / (float)max_steps; - } - else { - max_steps = max((int)ceilf(ray->t/step_size), 1); - } + max_steps = kernel_data.integrator.volume_max_steps; + kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); + #ifdef __KERNEL_CPU__ /* NOTE: For the branched path tracing it's possible to have direct * and indirect light integration both having volume segments allocated. @@ -723,19 +737,18 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta sizeof(*kg->decoupled_volume_steps)); if(kg->decoupled_volume_steps[index] == NULL) { kg->decoupled_volume_steps[index] = - (VolumeStep*)malloc(sizeof(VolumeStep)*global_max_steps); + (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps); } segment->steps = kg->decoupled_volume_steps[index]; ++kg->decoupled_volume_steps_index; #else segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps); #endif - random_jitter_offset = lcg_step_float(&state->rng_congruential) * step_size; } else { max_steps = 1; step_size = ray->t; - random_jitter_offset = 0.0f; + step_offset = 0.0f; segment->steps = &segment->stack_step; } @@ -757,11 +770,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta 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(heterogeneous && new_t == ray->t) - random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt; + /* 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 + random_jitter_offset); + float3 new_P = ray->P + ray->D * (t + step_offset); VolumeShaderCoefficients coeff; /* compute segment */ @@ -818,7 +833,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta step->accum_transmittance = accum_transmittance; step->cdf_distance = cdf_distance; step->t = new_t; - step->shade_t = t + random_jitter_offset; + step->shade_t = t + step_offset; /* stop if at the end of the volume */ t = new_t; |