diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index a4a7a2db6f5..e6b3dd7521b 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -261,7 +261,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g ShaderData volume_sd; VolumeIntegrateResult result = kernel_volume_integrate(kg, &state, - &volume_sd, &volume_ray, L, &throughput, rng); + &volume_sd, &volume_ray, L, &throughput, rng, false); if(result == VOLUME_PATH_SCATTERED) { if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &throughput, &state, L, &ray, 1.0f)) @@ -650,7 +650,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, ShaderData volume_sd; VolumeIntegrateResult result = kernel_volume_integrate(kg, &state, - &volume_sd, &volume_ray, &L, &throughput, rng); + &volume_sd, &volume_ray, &L, &throughput, rng, false); if(result == VOLUME_PATH_SCATTERED) { if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &throughput, &state, &L, &ray, 1.0f)) @@ -1092,7 +1092,6 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in int num_samples = kernel_data.integrator.volume_samples; float num_samples_inv = 1.0f/num_samples; - float3 avg_tp = make_float3(0.0f, 0.0f, 0.0f); /* todo: we should cache the shader evaluations from stepping * through the volume, for now we redo them multiple times */ @@ -1107,7 +1106,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in path_state_branch(&ps, j, num_samples); VolumeIntegrateResult result = kernel_volume_integrate(kg, &ps, - &volume_sd, &volume_ray, &L, &tp, rng); + &volume_sd, &volume_ray, &L, &tp, rng, true); if(result == VOLUME_PATH_SCATTERED) { /* todo: use all-light sampling */ @@ -1120,11 +1119,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in path_radiance_reset_indirect(&L); } } - else - avg_tp += tp; } - throughput = avg_tp * num_samples_inv; + /* todo: avoid this calculation using decoupled ray marching */ + kernel_volume_shadow(kg, &state, &volume_ray, &throughput); } #endif diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index f2a02e17293..451d28bfb52 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -295,7 +295,7 @@ ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coe * the volume shading coefficient for the entire line segment */ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd, PathRadiance *L, float3 *throughput, - RNG *rng) + RNG *rng, bool branched) { VolumeShaderCoefficients coeff; @@ -318,19 +318,14 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba int channel = (int)(rphase*3.0f); sd->randb_closure = rphase*3.0f - channel; - /* decide if we will hit or miss */ float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE); - float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel); - float sample_transmittance = expf(-sample_sigma_t * t); - if(xi >= sample_transmittance) { - /* scattering */ + if(branched) { + /* branched path tracing: we always scatter in the segment */ float3 pdf; float sample_t; - /* rescale random number so we can reuse it */ - xi = (xi - sample_transmittance)/(1.0f - sample_transmittance); - + /* scattering */ if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) { /* distance sampling */ sample_t = kernel_volume_distance_sample(ray, sigma_t, channel, xi, &transmittance, &pdf); @@ -346,17 +341,52 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba pdf = make_float3(equi_pdf, equi_pdf, equi_pdf); } - /* modifiy pdf for hit/miss decision */ - pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t); - new_tp = *throughput * coeff.sigma_s * transmittance / ((pdf.x + pdf.y + pdf.z) * (1.0f/3.0f)); t = sample_t; } else { - /* no scattering */ - transmittance = volume_color_transmittance(sigma_t, t); - float pdf = (transmittance.x + transmittance.y + transmittance.z) * (1.0f/3.0f); - new_tp = *throughput * transmittance / pdf; + /* regular path tracing: we probalistically scatter in the segment + * with probability the transmittance over the segment */ + + /* decide if we will hit or miss */ + float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel); + float sample_transmittance = expf(-sample_sigma_t * t); + + if(xi >= sample_transmittance) { + /* scattering */ + float3 pdf; + float sample_t; + + /* rescale random number so we can reuse it */ + xi = (xi - sample_transmittance)/(1.0f - sample_transmittance); + + if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) { + /* distance sampling */ + sample_t = kernel_volume_distance_sample(ray, sigma_t, channel, xi, &transmittance, &pdf); + } + else { + /* equiangular sampling */ + float3 light_P; + float equi_pdf; + if(!kernel_volume_equiangular_light_position(kg, state, ray, rng, &light_P)) + return VOLUME_PATH_MISSED; + + sample_t = kernel_volume_equiangular_sample(ray, sigma_t, light_P, xi, &transmittance, &equi_pdf); + pdf = make_float3(equi_pdf, equi_pdf, equi_pdf); + } + + /* modifiy pdf for hit/miss decision */ + pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t); + + new_tp = *throughput * coeff.sigma_s * transmittance / ((pdf.x + pdf.y + pdf.z) * (1.0f/3.0f)); + t = sample_t; + } + else { + /* no scattering */ + transmittance = volume_color_transmittance(sigma_t, t); + float pdf = (transmittance.x + transmittance.y + transmittance.z) * (1.0f/3.0f); + new_tp = *throughput * transmittance / pdf; + } } } else if(closure_flag & SD_ABSORPTION) { @@ -547,7 +577,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo * ray, with the assumption that there are no surfaces blocking light * between the endpoints */ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals *kg, - PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng) + PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng, + bool branched) { /* workaround to fix correlation bug in T38710, can find better solution * in random number generator later, for now this is done here to not impact @@ -560,7 +591,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals if(heterogeneous) return kernel_volume_integrate_heterogeneous(kg, state, ray, sd, L, throughput, &tmp_rng); else - return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, &tmp_rng); + return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, &tmp_rng, branched); } /* Volume Stack