diff options
-rw-r--r-- | intern/cycles/kernel/kernel_bake.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 84 |
2 files changed, 83 insertions, 3 deletions
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index dfbb49db7e6..822ad14039b 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -96,7 +96,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian /* sample subsurface scattering */ if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) { /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */ - kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, throughput); + kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, throughput); } #endif diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 8e9fc743694..0515489f77f 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -359,6 +359,40 @@ ccl_device void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, PathR } #ifdef __SUBSURFACE__ + +# ifdef __VOLUME__ +ccl_device void kernel_path_subsurface_update_volume_stack(KernelGlobals *kg, + Ray *ray, + VolumeStack *stack) +{ + kernel_assert(kernel_data.integrator.use_volumes); + + Ray volume_ray = *ray; + Intersection isect; + const float3 Pend = volume_ray.P + volume_ray.D*volume_ray.t; + + while( + scene_intersect(kg, &volume_ray, PATH_RAY_ALL_VISIBILITY, + &isect, NULL, 0.0f, 0.0f)) { + ShaderData sd; + shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); + kernel_volume_stack_enter_exit(kg, &sd, stack); + + /* Move ray forward. */ + volume_ray.P = ray_offset(sd.P, -sd.Ng); + volume_ray.D = normalize_len(Pend - volume_ray.P, + &volume_ray.t); + + /* TODO(sergey): Find a faster way detecting that ray_offset moved + * us pass through the end point. + */ + if(dot(ray->D, volume_ray.D) < 0.0f) { + break; + } + } +} +# endif + ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput) { float bssrdf_probability; @@ -375,6 +409,9 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd float bssrdf_u, bssrdf_v; path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false); +#ifdef __VOLUME__ + Ray volume_ray = *ray; +#endif /* compute lighting with the BSDF closure */ for(int hit = 0; hit < num_hits; hit++) { @@ -392,6 +429,22 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd hit_state.ray_t = 0.0f; #endif +#ifdef __VOLUME__ + if(kernel_data.integrator.use_volumes) { + /* Setup ray from previous surface point to the new one. */ + volume_ray.D = normalize_len(hit_ray.P - volume_ray.P, + &volume_ray.t); + + kernel_path_subsurface_update_volume_stack( + kg, + &volume_ray, + hit_state.volume_stack); + + /* Move volume ray forward. */ + volume_ray.P = hit_ray.P; + } +#endif + kernel_path_indirect(kg, rng, hit_ray, tp, state->num_samples, hit_state, L); /* for render passes, sum and reset indirect light pass variables @@ -718,7 +771,13 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba } #ifdef __SUBSURFACE__ -ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, float3 throughput) +ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, + ShaderData *sd, + PathRadiance *L, + PathState *state, + RNG *rng, + Ray *ray, + float3 throughput) { for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; @@ -741,6 +800,9 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, Shade float bssrdf_u, bssrdf_v; path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true); +# ifdef __VOLUME__ + Ray volume_ray = *ray; +# endif /* compute lighting with the BSDF closure */ for(int hit = 0; hit < num_hits; hit++) { @@ -748,6 +810,23 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, Shade path_state_branch(&hit_state, j, num_samples); +#ifdef __VOLUME__ + if(kernel_data.integrator.use_volumes) { + /* Setup ray from previous surface point to the new one. */ + float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng); + volume_ray.D = normalize_len(P - volume_ray.P, + &volume_ray.t); + + kernel_path_subsurface_update_volume_stack( + kg, + &volume_ray, + hit_state.volume_stack); + + /* Move volume ray forward. */ + volume_ray.P = P; + } +#endif + #if defined(__EMISSION__) && defined(__BRANCHED_PATH__) /* direct light */ if(kernel_data.integrator.use_direct_light) { @@ -1012,7 +1091,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in #ifdef __SUBSURFACE__ /* bssrdf scatter to a different location on the same object */ if(sd.flag & SD_BSSRDF) { - kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state, rng, throughput); + kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state, + rng, &ray, throughput); } #endif |