diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 3ef472b248e..d760af15def 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -281,7 +281,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, /* setup shading */ ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce); - float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF); + float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF); shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_INDIRECT); #ifdef __BRANCHED_PATH__ shader_merge_closures(&sd); @@ -315,7 +315,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, break; } else if(probability != 1.0f) { - float terminate = path_state_rng_1D(kg, rng, &state, PRNG_TERMINATE); + float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE); if(terminate >= probability) break; @@ -785,7 +785,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, /* setup shading */ ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce, state.transparent_bounce); - float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF); + float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF); shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN); /* holdout */ @@ -840,7 +840,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, break; } else if(probability != 1.0f) { - float terminate = path_state_rng_1D(kg, rng, &state, PRNG_TERMINATE); + float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE); if(terminate >= probability) break; @@ -1325,7 +1325,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in break; } else if(probability != 1.0f) { - float terminate = path_state_rng_1D(kg, rng, &state, PRNG_TERMINATE); + float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE); if(terminate >= probability) break; diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 406654c1741..39780c0edb0 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -63,8 +63,8 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int state->flag |= PATH_RAY_TRANSPARENT; state->transparent_bounce++; - /* random number generator next bounce */ - state->rng_offset += PRNG_BOUNCE_NUM; + /* don't increase random number generator offset here, to avoid some + * unwanted patterns, see path_state_rng_1D_for_decision */ if(!kernel_data.integrator.transparent_shadows) state->flag |= PATH_RAY_MIS_SKIP; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 31cb6ff6abd..ac04b3168a1 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -266,6 +266,19 @@ ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, PathState return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension); } +ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, PathState *state, int dimension) +{ + /* the rng_offset is not increased for transparent bounces. if we do then + * fully transparent objects can become subtly visible by the different + * sampling patterns used where the transparent object is. + * + * however for some random numbers that will determine if we next bounce + * is transparent we do need to increase the offset to avoid always making + * the same decision */ + int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM; + return path_rng_1D(kg, rng, state->sample, state->num_samples, rng_offset + dimension); +} + ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, PathState *state, int dimension, float *fx, float *fy) { path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 11445aa1c93..7edbf5ab172 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -686,9 +686,10 @@ typedef struct PathState { int flag; /* random number generator state */ - int rng_offset; /* dimension offset */ - int sample; /* path sample number */ - int num_samples; /* total number of times this path will be sampled */ + int rng_offset; /* dimension offset */ + int rng_offset_bsdf; /* dimension offset for picking bsdf */ + int sample; /* path sample number */ + int num_samples; /* total number of times this path will be sampled */ /* bounce counting */ int bounce; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 75c81940bbb..49e4cf64de4 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -322,11 +322,11 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba /* pick random color channel, we use the Veach one-sample * model with balance heuristic for the channels */ - float rphase = path_state_rng_1D(kg, rng, state, PRNG_PHASE); + float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE); int channel = (int)(rphase*3.0f); sd->randb_closure = rphase*3.0f - channel; - float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE); + float xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE); /* decide if we will hit or miss */ float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel); @@ -461,9 +461,9 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo if(channel == -1) { /* pick random color channel, we use the Veach one-sample * model with balance heuristic for the channels */ - xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE); + xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE); - float rphase = path_state_rng_1D(kg, rng, state, PRNG_PHASE); + float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE); channel = (int)(rphase*3.0f); sd->randb_closure = rphase*3.0f - channel; } @@ -710,11 +710,11 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter( /* pick random color channel, we use the Veach one-sample * model with balance heuristic for the channels */ - float rphase = path_state_rng_1D(kg, rng, state, PRNG_PHASE); + float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE); int channel = (int)(rphase*3.0f); sd->randb_closure = rphase*3.0f - channel; - float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE); + float xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE); VolumeStep *step; float3 transmittance;