diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-03-01 01:00:46 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-03-01 03:21:29 +0300 |
commit | 7f86afec9d6799e22127c53d9d0805a87462fc08 (patch) | |
tree | 566aca7a18e47b45251b10fcb5b4393c0d3562a8 /intern/cycles/kernel/split | |
parent | 03d10703783a0d233517aac558ac3f0a7d55d302 (diff) |
Cycles: don't count volume boundaries as transparent bounces.
This is more important now that we will have tigther volume bounds that
we hit multiple times. It also avoids some noise due to RR previously
affecting these surfaces, which shouldn't have been the case and should
eventually be fixed for transparent BSDFs as well.
For non-volume scenes I found no performance impact on NVIDIA or AMD.
For volume scenes the noise decrease and fixed artifacts are worth the
little extra render time, when there is any.
Diffstat (limited to 'intern/cycles/kernel/split')
-rw-r--r-- | intern/cycles/kernel/split/kernel_next_iteration_setup.h | 63 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_queue_enqueue.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_shader_setup.h | 10 |
3 files changed, 54 insertions, 20 deletions
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h index 81024f0cf99..8092419e796 100644 --- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h +++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h @@ -53,39 +53,52 @@ ccl_device_inline void kernel_split_branched_indirect_light_init(KernelGlobals * ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT); } -ccl_device void kernel_split_branched_indirect_light_end(KernelGlobals *kg, int ray_index) +ccl_device void kernel_split_branched_transparent_bounce(KernelGlobals *kg, int ray_index) { - kernel_split_branched_path_indirect_loop_end(kg, ray_index); - ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; ShaderData *sd = kernel_split_sd(sd, ray_index); ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - /* continue in case of transparency */ - *throughput *= shader_bsdf_transparency(kg, sd); +# ifdef __VOLUME__ + if(!(sd->flag & SD_HAS_ONLY_VOLUME)) { +# endif + /* continue in case of transparency */ + *throughput *= shader_bsdf_transparency(kg, sd); + + if(is_zero(*throughput)) { + kernel_split_path_end(kg, ray_index); + return; + } - if(is_zero(*throughput)) { - kernel_split_path_end(kg, ray_index); - } - else { /* Update Path State */ path_state_next(kg, state, LABEL_TRANSPARENT); +# ifdef __VOLUME__ + } + else { + /* For volume bounding meshes we pass through without counting transparent + * bounces, only sanity check in case self intersection gets us stuck. */ + state->volume_bounds_bounce++; + if (state->volume_bounds_bounce > VOLUME_BOUNDS_MAX) { + kernel_split_path_end(kg, ray_index); + return; + } + } +# endif - ray->P = ray_offset(sd->P, -sd->Ng); - ray->t -= sd->ray_length; /* clipping works through transparent */ + ray->P = ray_offset(sd->P, -sd->Ng); + ray->t -= sd->ray_length; /* clipping works through transparent */ # ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; - ray->dD.dx = -sd->dI.dx; - ray->dD.dy = -sd->dI.dy; + ray->dP = sd->dP; + ray->dD.dx = -sd->dI.dx; + ray->dD.dy = -sd->dI.dy; # endif /* __RAY_DIFFERENTIALS__ */ # ifdef __VOLUME__ - /* enter/exit volume */ - kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); + /* enter/exit volume */ + kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); # endif /* __VOLUME__ */ - } } #endif /* __BRANCHED_PATH__ */ @@ -121,6 +134,13 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ccl_global char *ray_state = kernel_split_state.ray_state; +# ifdef __VOLUME__ + /* Reactivate only volume rays here, most surface work was skipped. */ + if(IS_STATE(ray_state, ray_index, RAY_HAS_ONLY_VOLUME)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE); + } +# endif + bool active = IS_STATE(ray_state, ray_index, RAY_ACTIVE); if(active) { ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; @@ -138,6 +158,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, } #ifdef __BRANCHED_PATH__ } + else if(sd->flag & SD_HAS_ONLY_VOLUME) { + kernel_split_branched_transparent_bounce(kg, ray_index); + } else { kernel_split_branched_indirect_light_init(kg, ray_index); @@ -151,7 +174,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); } else { - kernel_split_branched_indirect_light_end(kg, ray_index); + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + kernel_split_branched_transparent_bounce(kg, ray_index); } } #endif /* __BRANCHED_PATH__ */ @@ -196,7 +220,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); } else { - kernel_split_branched_indirect_light_end(kg, ray_index); + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + kernel_split_branched_transparent_bounce(kg, ray_index); } } diff --git a/intern/cycles/kernel/split/kernel_queue_enqueue.h b/intern/cycles/kernel/split/kernel_queue_enqueue.h index 66ce2dfb6f1..df67fabab19 100644 --- a/intern/cycles/kernel/split/kernel_queue_enqueue.h +++ b/intern/cycles/kernel/split/kernel_queue_enqueue.h @@ -56,6 +56,7 @@ ccl_device void kernel_queue_enqueue(KernelGlobals *kg, queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS; } else if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) || + IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME) || IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) { queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS; } diff --git a/intern/cycles/kernel/split/kernel_shader_setup.h b/intern/cycles/kernel/split/kernel_shader_setup.h index 9d428ee8139..ea3ec2ec83f 100644 --- a/intern/cycles/kernel/split/kernel_shader_setup.h +++ b/intern/cycles/kernel/split/kernel_shader_setup.h @@ -59,12 +59,20 @@ ccl_device void kernel_shader_setup(KernelGlobals *kg, if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) { Intersection isect = kernel_split_state.isect[ray_index]; Ray ray = kernel_split_state.ray[ray_index]; + ShaderData *sd = kernel_split_sd(sd, ray_index); shader_setup_from_ray(kg, - kernel_split_sd(sd, ray_index), + sd, &isect, &ray); + +#ifdef __VOLUME__ + if(sd->flag & SD_HAS_ONLY_VOLUME) { + ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME); + } +#endif } + } CCL_NAMESPACE_END |