diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-09-13 16:44:13 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-09-13 16:44:13 +0300 |
commit | 37d8d4787cfa3d04b09f935c5600f1a3ea7b74e7 (patch) | |
tree | b60dfc428ccd61b5b3af6a06cee6ddbe69d3973e /intern | |
parent | 9abacf38fd4f3b0de4b6d9a4644b9cb1155482c9 (diff) | |
parent | 6f633dec5d105ad91dcb5774a6fd4fb06bf264a5 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'intern')
27 files changed, 763 insertions, 1058 deletions
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index f733ea4c517..06221189060 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -348,8 +348,9 @@ ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight) { Bssrdf *bssrdf = (Bssrdf*)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight); - if(!bssrdf) + if(bssrdf == NULL) { return NULL; + } float sample_weight = fabsf(average(weight)); bssrdf->sample_weight = sample_weight; diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 82d3c153bf5..5e604586557 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -226,9 +226,9 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) L->path_total = make_float3(0.0f, 0.0f, 0.0f); L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f); L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f); - L->shadow_radiance_sum = make_float3(0.0f, 0.0f, 0.0f); L->shadow_throughput = 0.0f; L->shadow_transparency = 1.0f; + L->has_shadow_catcher = 0; #endif #ifdef __DENOISING_FEATURES__ @@ -279,13 +279,22 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space } } -ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce) +ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, + ccl_addr_space PathState *state, + float3 throughput, + float3 value) { +#ifdef __SHADOW_TRICKS__ + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + return; + } +#endif + #ifdef __PASSES__ if(L->use_light_pass) { - if(bounce == 0) + if(state->bounce == 0) L->emission += throughput*value; - else if(bounce == 1) + else if(state->bounce == 1) L->direct_emission += throughput*value; else L->indirect += throughput*value; @@ -304,6 +313,18 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 bsdf, float3 ao) { +#ifdef __SHADOW_TRICKS__ + if(state->flag & PATH_RAY_STORE_SHADOW_INFO) { + float3 light = throughput * bsdf; + L->path_total += light; + L->path_total_shaded += ao * light; + + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + return; + } + } +#endif + #ifdef __PASSES__ if(L->use_light_pass) { if(state->bounce == 0) { @@ -321,14 +342,6 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, { L->emission += throughput*bsdf*ao; } - -#ifdef __SHADOW_TRICKS__ - if(state->flag & PATH_RAY_STORE_SHADOW_INFO) { - float3 light = throughput * bsdf; - L->path_total += light; - L->path_total_shaded += ao * light; - } -#endif } ccl_device_inline void path_radiance_accum_total_ao( @@ -357,6 +370,18 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float shadow_fac, bool is_lamp) { +#ifdef __SHADOW_TRICKS__ + if(state->flag & PATH_RAY_STORE_SHADOW_INFO) { + float3 light = throughput * bsdf_eval->sum_no_mis; + L->path_total += light; + L->path_total_shaded += shadow * light; + + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + return; + } + } +#endif + #ifdef __PASSES__ if(L->use_light_pass) { if(state->bounce == 0) { @@ -383,14 +408,6 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, { L->emission += throughput*bsdf_eval->diffuse*shadow; } - -#ifdef __SHADOW_TRICKS__ - if(state->flag & PATH_RAY_STORE_SHADOW_INFO) { - float3 light = throughput * bsdf_eval->sum_no_mis; - L->path_total += light; - L->path_total_shaded += shadow * light; - } -#endif } ccl_device_inline void path_radiance_accum_total_light( @@ -417,6 +434,18 @@ ccl_device_inline void path_radiance_accum_background( float3 throughput, float3 value) { + +#ifdef __SHADOW_TRICKS__ + if(state->flag & PATH_RAY_STORE_SHADOW_INFO) { + L->path_total += throughput * value; + L->path_total_shaded += throughput * value * L->shadow_transparency; + + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + return; + } + } +#endif + #ifdef __PASSES__ if(L->use_light_pass) { if(state->bounce == 0) @@ -432,18 +461,31 @@ ccl_device_inline void path_radiance_accum_background( L->emission += throughput*value; } -#ifdef __SHADOW_TRICKS__ - if(state->flag & PATH_RAY_STORE_SHADOW_INFO) { - L->path_total += throughput * value; - L->path_total_shaded += throughput * value * L->shadow_transparency; - } -#endif - #ifdef __DENOISING_FEATURES__ L->denoising_albedo += state->denoising_feature_weight * value; #endif /* __DENOISING_FEATURES__ */ } +ccl_device_inline void path_radiance_accum_transparent( + PathRadiance *L, + ccl_addr_space PathState *state, + float3 throughput) +{ + L->transparent += average(throughput); +} + +#ifdef __SHADOW_TRICKS__ +ccl_device_inline void path_radiance_accum_shadowcatcher( + PathRadiance *L, + float3 throughput, + float3 background) +{ + L->shadow_throughput += average(throughput); + L->shadow_background_color += throughput * background; + L->has_shadow_catcher = 1; +} +#endif + ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L) { #ifdef __PASSES__ @@ -501,7 +543,36 @@ ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L, #endif } -ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L) +#ifdef __SHADOW_TRICKS__ +ccl_device_inline void path_radiance_sum_shadowcatcher(KernelGlobals *kg, + PathRadiance *L, + float3 *L_sum, + float *alpha) +{ + /* Calculate current shadow of the path. */ + float path_total = average(L->path_total); + float shadow; + + if(path_total == 0.0f) { + shadow = L->shadow_transparency; + } + else { + float path_total_shaded = average(L->path_total_shaded); + shadow = path_total_shaded / path_total; + } + + /* Calculate final light sum and transparency for shadow catcher object. */ + if(kernel_data.background.transparent) { + *alpha -= L->shadow_throughput * shadow; + } + else { + L->shadow_background_color *= shadow; + *L_sum += L->shadow_background_color; + } +} +#endif + +ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L, float *alpha) { float3 L_sum; /* Light Passes are used */ @@ -578,8 +649,6 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi L_sum = L_direct + L_indirect; } #endif - - return L_sum; } /* No Light Passes */ @@ -587,14 +656,24 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi #endif { L_sum = L->emission; + + /* Reject invalid value */ + float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z); + if(!isfinite_safe(sum)) { + kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!"); + L_sum = make_float3(0.0f, 0.0f, 0.0f); + } } - /* Reject invalid value */ - float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z); - if(!isfinite_safe(sum)) { - kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!"); - L_sum = make_float3(0.0f, 0.0f, 0.0f); + /* Compute alpha. */ + *alpha = 1.0f - L->transparent; + + /* Add shadow catcher contributions. */ +#ifdef __SHADOW_TRICKS__ + if(L->has_shadow_catcher) { + path_radiance_sum_shadowcatcher(kg, L, &L_sum, alpha); } +#endif /* __SHADOW_TRICKS__ */ return L_sum; } @@ -627,14 +706,18 @@ ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg, PathRadi *clean = make_float3(0.0f, 0.0f, 0.0f); #endif +#ifdef __SHADOW_TRICKS__ + if(L->has_shadow_catcher) { + *noisy += L->shadow_background_color; + } +#endif + *noisy = ensure_finite3(*noisy); *clean = ensure_finite3(*clean); } -ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample, int num_samples) +ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample) { - float fac = 1.0f/num_samples; - #ifdef __SPLIT_KERNEL__ # define safe_float3_add(f, v) \ do { \ @@ -643,66 +726,35 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance atomic_add_and_fetch_float(p+1, (v).y); \ atomic_add_and_fetch_float(p+2, (v).z); \ } while(0) +# define safe_float_add(f, v) \ + atomic_add_and_fetch_float(&(f), (v)) #else # define safe_float3_add(f, v) (f) += (v) +# define safe_float_add(f, v) (f) += (v) #endif /* __SPLIT_KERNEL__ */ #ifdef __PASSES__ - safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse*fac); - safe_float3_add(L->direct_glossy, L_sample->direct_glossy*fac); - safe_float3_add(L->direct_transmission, L_sample->direct_transmission*fac); - safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface*fac); - safe_float3_add(L->direct_scatter, L_sample->direct_scatter*fac); - - safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse*fac); - safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy*fac); - safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission*fac); - safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface*fac); - safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter*fac); - - safe_float3_add(L->background, L_sample->background*fac); - safe_float3_add(L->ao, L_sample->ao*fac); - safe_float3_add(L->shadow, L_sample->shadow*fac); -# ifdef __SPLIT_KERNEL__ - atomic_add_and_fetch_float(&L->mist, L_sample->mist*fac); -# else - L->mist += L_sample->mist*fac; -# endif /* __SPLIT_KERNEL__ */ + safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse); + safe_float3_add(L->direct_glossy, L_sample->direct_glossy); + safe_float3_add(L->direct_transmission, L_sample->direct_transmission); + safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface); + safe_float3_add(L->direct_scatter, L_sample->direct_scatter); + + safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse); + safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy); + safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission); + safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface); + safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter); + + safe_float3_add(L->background, L_sample->background); + safe_float3_add(L->ao, L_sample->ao); + safe_float3_add(L->shadow, L_sample->shadow); + safe_float_add(L->mist, L_sample->mist); #endif /* __PASSES__ */ - safe_float3_add(L->emission, L_sample->emission*fac); + safe_float3_add(L->emission, L_sample->emission); +#undef safe_float_add #undef safe_float3_add } -#ifdef __SHADOW_TRICKS__ -/* Calculate current shadow of the path. */ -ccl_device_inline float path_radiance_sum_shadow(const PathRadiance *L) -{ - float path_total = average(L->path_total); - float path_total_shaded = average(L->path_total_shaded); - if(path_total != 0.0f) { - return path_total_shaded / path_total; - } - return L->shadow_transparency; -} - -/* Calculate final light sum and transparency for shadow catcher object. */ -ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg, - const PathRadiance *L, - float* alpha) -{ - const float shadow = path_radiance_sum_shadow(L); - float3 L_sum; - if(kernel_data.background.transparent) { - *alpha = 1.0f - L->shadow_throughput * shadow; - L_sum = L->shadow_radiance_sum; - } - else { - L_sum = L->shadow_background_color * L->shadow_throughput * shadow + - L->shadow_radiance_sum; - } - return L_sum; -} -#endif - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index 8af1187213d..b05f6e9ed5e 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -70,7 +70,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg, /* sample emission */ if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) { float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf); - path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce); + path_radiance_accum_emission(&L_sample, &state, throughput, emission); } bool is_sss_sample = false; @@ -102,7 +102,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg, &emission_sd, &ray, throughput, - state.num_samples, &state, &L_sample); kernel_path_subsurface_accum_indirect(&ss_indirect, &L_sample); @@ -121,7 +120,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg, state.ray_t = 0.0f; #endif /* compute indirect light */ - kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, 1, &state, &L_sample); + kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample); /* sum and reset indirect light pass variables for the next samples */ path_radiance_sum_indirect(&L_sample); @@ -141,7 +140,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg, /* sample emission */ if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) { float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf); - path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce); + path_radiance_accum_emission(&L_sample, &state, throughput, emission); } #ifdef __SUBSURFACE__ @@ -172,7 +171,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg, #endif /* accumulate into master L */ - path_radiance_accum_sample(L, &L_sample, 1); + path_radiance_accum_sample(L, &L_sample); } ccl_device bool is_aa_pass(ShaderEvalType type) @@ -368,7 +367,8 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, case SHADER_EVAL_COMBINED: { if((pass_filter & BAKE_FILTER_COMBINED) == BAKE_FILTER_COMBINED) { - out = path_radiance_clamp_and_sum(kg, &L); + float alpha; + out = path_radiance_clamp_and_sum(kg, &L, &alpha); break; } diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 48a8e53be33..13d4759a9ec 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -37,9 +37,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, ray.D = ls->D; ray.P = ls->P; ray.t = 1.0f; -# ifdef __OBJECT_MOTION__ ray.time = time; -# endif ray.dP = differential3_zero(); ray.dD = dI; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 59db6cbd430..c806deee8e7 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -396,11 +396,13 @@ ccl_device_inline float3 background_light_sample(KernelGlobals *kg, + (1.0f - portal_sampling_pdf) * cdf_pdf); } return D; - } else { + } + else { /* Sample map, but with nonzero portal_sampling_pdf for MIS. */ randu = (randu - portal_sampling_pdf) / (1.0f - portal_sampling_pdf); } - } else { + } + else { /* We can't sample a portal. * Check if we can sample the map instead. */ @@ -772,7 +774,8 @@ ccl_device_inline bool triangle_world_space_vertices(KernelGlobals *kg, int obje if(object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) { motion_triangle_vertices(kg, object, prim, time, V); has_motion = true; - } else { + } + else { triangle_vertices(kg, prim, V); } @@ -839,13 +842,15 @@ ccl_device_forceinline float triangle_light_pdf(KernelGlobals *kg, ShaderData *s /* pdf_triangles is calculated over triangle area, but we're not sampling over its area */ if(UNLIKELY(solid_angle == 0.0f)) { return 0.0f; - } else { + } + else { float area = 1.0f; if(has_motion) { /* get the center frame vertices, this is what the PDF was calculated from */ triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V); area = triangle_area(V[0], V[1], V[2]); - } else { + } + else { area = 0.5f * len(N); } const float pdf = area * kernel_data.integrator.pdf_triangles; @@ -965,19 +970,25 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, i ls->D = z * B + safe_sqrtf(1.0f - z*z) * safe_normalize(C_ - dot(C_, B) * B); /* calculate intersection with the planar triangle */ - ray_triangle_intersect(P, ls->D, FLT_MAX, + if(!ray_triangle_intersect(P, ls->D, FLT_MAX, #if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__) - (ssef*)V, + (ssef*)V, #else - V[0], V[1], V[2], + V[0], V[1], V[2], #endif - &ls->u, &ls->v, &ls->t); + &ls->u, &ls->v, &ls->t)) { + ls->pdf = 0.0f; + return; + } + ls->P = P + ls->D * ls->t; /* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */ if(UNLIKELY(solid_angle == 0.0f)) { ls->pdf = 0.0f; - } else { + return; + } + else { if(has_motion) { /* get the center frame vertices, this is what the PDF was calculated from */ triangle_world_space_vertices(kg, object, prim, -1.0f, V); @@ -1013,20 +1024,21 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, i /* Light Distribution */ -ccl_device int light_distribution_sample(KernelGlobals *kg, float randt) +ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) { - /* this is basically std::upper_bound as used by pbrt, to find a point light or + /* This is basically std::upper_bound as used by pbrt, to find a point light or * triangle to emit from, proportional to area. a good improvement would be to * also sample proportional to power, though it's not so well defined with - * OSL shaders. */ + * arbitrary shaders. */ int first = 0; int len = kernel_data.integrator.num_distribution + 1; + float r = *randu; while(len > 0) { int half_len = len >> 1; int middle = first + half_len; - if(randt < kernel_tex_fetch(__light_distribution, middle).x) { + if(r < kernel_tex_fetch(__light_distribution, middle).x) { len = half_len; } else { @@ -1035,9 +1047,17 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt) } } - /* clamping should not be needed but float rounding errors seem to - * make this fail on rare occasions */ - return clamp(first-1, 0, kernel_data.integrator.num_distribution-1); + /* Clamping should not be needed but float rounding errors seem to + * make this fail on rare occasions. */ + int index = clamp(first-1, 0, kernel_data.integrator.num_distribution-1); + + /* Rescale to reuse random number. this helps the 2D samples within + * each area light be stratified as well. */ + float distr_min = kernel_tex_fetch(__light_distribution, index).x; + float distr_max = kernel_tex_fetch(__light_distribution, index+1).x; + *randu = (r - distr_min)/(distr_max - distr_min); + + return index; } /* Generic Light */ @@ -1049,7 +1069,6 @@ ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, i } ccl_device_noinline bool light_sample(KernelGlobals *kg, - float randt, float randu, float randv, float time, @@ -1058,7 +1077,7 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg, LightSample *ls) { /* sample index */ - int index = light_distribution_sample(kg, randt); + int index = light_distribution_sample(kg, &randu); /* fetch light data */ float4 l = kernel_tex_fetch(__light_distribution, index); diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index d454cce6e30..fff7f4cfdb7 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -225,7 +225,7 @@ ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg, #endif /* __KERNEL_DEBUG__ */ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L, - ShaderData *sd, int sample, ccl_addr_space PathState *state, float3 throughput) + ShaderData *sd, ccl_addr_space PathState *state, float3 throughput) { #ifdef __PASSES__ int path_flag = state->flag; @@ -243,6 +243,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl kernel_data.film.pass_alpha_threshold == 0.0f || average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) { + int sample = state->sample; if(sample == 0) { if(flag & PASS_DEPTH) { @@ -364,21 +365,11 @@ ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, ccl_global f } ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *buffer, - int sample, PathRadiance *L, bool is_shadow_catcher) + int sample, PathRadiance *L) { if(L) { - float3 L_sum; - float alpha = 1.0f - L->transparent; - -#ifdef __SHADOW_TRICKS__ - if(is_shadow_catcher) { - L_sum = path_radiance_sum_shadowcatcher(kg, L, &alpha); - } - else -#endif /* __SHADOW_TRICKS__ */ - { - L_sum = path_radiance_clamp_and_sum(kg, L); - } + float alpha; + float3 L_sum = path_radiance_clamp_and_sum(kg, L, &alpha); kernel_write_pass_float4(buffer, sample, make_float4(L_sum.x, L_sum.y, L_sum.z, alpha)); @@ -393,16 +384,7 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float * # endif if(kernel_data.film.pass_denoising_clean) { float3 noisy, clean; -#ifdef __SHADOW_TRICKS__ - if(is_shadow_catcher) { - noisy = L_sum; - clean = make_float3(0.0f, 0.0f, 0.0f); - } - else -#endif /* __SHADOW_TRICKS__ */ - { - path_radiance_split_denoising(kg, L, &noisy, &clean); - } + path_radiance_split_denoising(kg, L, &noisy, &clean); kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR, sample, noisy); kernel_write_pass_float3_unaligned(buffer + kernel_data.film.pass_denoising_clean, diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 3319e2c2435..fc157feb28c 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -50,6 +50,294 @@ CCL_NAMESPACE_BEGIN +ccl_device_forceinline bool kernel_path_scene_intersect( + KernelGlobals *kg, + ccl_addr_space PathState *state, + Ray *ray, + Intersection *isect, + PathRadiance *L) +{ + uint visibility = path_state_ray_visibility(kg, state); + +#ifdef __HAIR__ + float difl = 0.0f, extmax = 0.0f; + uint lcg_state = 0; + + if(kernel_data.bvh.have_curves) { + if((kernel_data.cam.resolution == 1) && (state->flag & PATH_RAY_CAMERA)) { + float3 pixdiff = ray->dD.dx + ray->dD.dy; + /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/ + difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f; + } + + extmax = kernel_data.curve.maximum_width; + lcg_state = lcg_state_init_addrspace(state, 0x51633e2d); + } + + if(path_state_ao_bounce(kg, state)) { + visibility = PATH_RAY_SHADOW; + ray->t = kernel_data.background.ao_distance; + } + + bool hit = scene_intersect(kg, *ray, visibility, isect, &lcg_state, difl, extmax); +#else + bool hit = scene_intersect(kg, *ray, visibility, isect, NULL, 0.0f, 0.0f); +#endif /* __HAIR__ */ + +#ifdef __KERNEL_DEBUG__ + if(state->flag & PATH_RAY_CAMERA) { + L->debug_data.num_bvh_traversed_nodes += isect->num_traversed_nodes; + L->debug_data.num_bvh_traversed_instances += isect->num_traversed_instances; + L->debug_data.num_bvh_intersections += isect->num_intersections; + } + L->debug_data.num_ray_bounces++; +#endif /* __KERNEL_DEBUG__ */ + + return hit; +} + +ccl_device_forceinline void kernel_path_lamp_emission( + KernelGlobals *kg, + ccl_addr_space PathState *state, + Ray *ray, + float3 throughput, + ccl_addr_space Intersection *isect, + ShaderData *emission_sd, + PathRadiance *L) +{ +#ifdef __LAMP_MIS__ + if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) { + /* ray starting from previous non-transparent bounce */ + Ray light_ray; + + light_ray.P = ray->P - state->ray_t*ray->D; + state->ray_t += isect->t; + light_ray.D = ray->D; + light_ray.t = state->ray_t; + light_ray.time = ray->time; + light_ray.dD = ray->dD; + light_ray.dP = ray->dP; + + /* intersect with lamp */ + float3 emission; + + if(indirect_lamp_emission(kg, emission_sd, state, &light_ray, &emission)) + path_radiance_accum_emission(L, state, throughput, emission); + } +#endif /* __LAMP_MIS__ */ +} + +ccl_device_forceinline void kernel_path_background( + KernelGlobals *kg, + ccl_addr_space PathState *state, + ccl_addr_space Ray *ray, + float3 throughput, + ShaderData *emission_sd, + PathRadiance *L) +{ + /* eval background shader if nothing hit */ + if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) { + L->transparent += average(throughput); + +#ifdef __PASSES__ + if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) +#endif /* __PASSES__ */ + return; + } + +#ifdef __BACKGROUND__ + /* sample background shader */ + float3 L_background = indirect_background(kg, emission_sd, state, ray); + path_radiance_accum_background(L, state, throughput, L_background); +#endif /* __BACKGROUND__ */ +} + +#ifndef __SPLIT_KERNEL__ + +ccl_device_forceinline VolumeIntegrateResult kernel_path_volume( + KernelGlobals *kg, + ShaderData *sd, + PathState *state, + Ray *ray, + float3 *throughput, + ccl_addr_space Intersection *isect, + bool hit, + ShaderData *emission_sd, + PathRadiance *L) +{ +#ifdef __VOLUME__ + /* Sanitize volume stack. */ + if(!hit) { + kernel_volume_clean_stack(kg, state->volume_stack); + } + /* volume attenuation, emission, scatter */ + if(state->volume_stack[0].shader != SHADER_NONE) { + Ray volume_ray = *ray; + volume_ray.t = (hit)? isect->t: FLT_MAX; + + bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack); + +# ifdef __VOLUME_DECOUPLED__ + int sampling_method = volume_stack_sampling_method(kg, state->volume_stack); + bool direct = (state->flag & PATH_RAY_CAMERA) != 0; + bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, direct, sampling_method); + + if(decoupled) { + /* cache steps along volume for repeated sampling */ + VolumeSegment volume_segment; + + shader_setup_from_volume(kg, sd, &volume_ray); + kernel_volume_decoupled_record(kg, state, + &volume_ray, sd, &volume_segment, heterogeneous); + + volume_segment.sampling_method = sampling_method; + + /* emission */ + if(volume_segment.closure_flag & SD_EMISSION) + path_radiance_accum_emission(L, state, *throughput, volume_segment.accum_emission); + + /* scattering */ + VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED; + + if(volume_segment.closure_flag & SD_SCATTER) { + int all = kernel_data.integrator.sample_all_lights_indirect; + + /* direct light sampling */ + kernel_branched_path_volume_connect_light(kg, sd, + emission_sd, *throughput, state, L, all, + &volume_ray, &volume_segment); + + /* indirect sample. if we use distance sampling and take just + * one sample for direct and indirect light, we could share + * this computation, but makes code a bit complex */ + float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE); + float rscatter = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE); + + result = kernel_volume_decoupled_scatter(kg, + state, &volume_ray, sd, throughput, + rphase, rscatter, &volume_segment, NULL, true); + } + + /* free cached steps */ + kernel_volume_decoupled_free(kg, &volume_segment); + + if(result == VOLUME_PATH_SCATTERED) { + if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray)) + return VOLUME_PATH_SCATTERED; + else + return VOLUME_PATH_MISSED; + } + else { + *throughput *= volume_segment.accum_transmittance; + } + } + else +# endif /* __VOLUME_DECOUPLED__ */ + { + /* integrate along volume segment with distance sampling */ + VolumeIntegrateResult result = kernel_volume_integrate( + kg, state, sd, &volume_ray, L, throughput, heterogeneous); + +# ifdef __VOLUME_SCATTER__ + if(result == VOLUME_PATH_SCATTERED) { + /* direct lighting */ + kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L); + + /* indirect light bounce */ + if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray)) + return VOLUME_PATH_SCATTERED; + else + return VOLUME_PATH_MISSED; + } +# endif /* __VOLUME_SCATTER__ */ + } + } +#endif /* __VOLUME__ */ + + return VOLUME_PATH_ATTENUATED; +} + +#endif /* __SPLIT_KERNEL__ */ + +ccl_device_forceinline bool kernel_path_shader_apply( + KernelGlobals *kg, + ShaderData *sd, + ccl_addr_space PathState *state, + ccl_addr_space Ray *ray, + float3 throughput, + ShaderData *emission_sd, + PathRadiance *L, + ccl_global float *buffer) +{ +#ifdef __SHADOW_TRICKS__ + if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if(state->flag & PATH_RAY_CAMERA) { + state->flag |= (PATH_RAY_SHADOW_CATCHER | + PATH_RAY_STORE_SHADOW_INFO); + + float3 bg = make_float3(0.0f, 0.0f, 0.0f); + if(!kernel_data.background.transparent) { + bg = indirect_background(kg, emission_sd, state, ray); + } + path_radiance_accum_shadowcatcher(L, throughput, bg); + } + } + else if(state->flag & PATH_RAY_SHADOW_CATCHER) { + /* Only update transparency after shadow catcher bounce. */ + L->shadow_transparency *= + average(shader_bsdf_transparency(kg, sd)); + } +#endif /* __SHADOW_TRICKS__ */ + + /* holdout */ +#ifdef __HOLDOUT__ + if(((sd->flag & SD_HOLDOUT) || + (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) && + (state->flag & PATH_RAY_CAMERA)) + { + if(kernel_data.background.transparent) { + float3 holdout_weight; + if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { + holdout_weight = make_float3(1.0f, 1.0f, 1.0f); + } + else { + holdout_weight = shader_holdout_eval(kg, sd); + } + /* any throughput is ok, should all be identical here */ + L->transparent += average(holdout_weight*throughput); + } + + if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { + return false; + } + } +#endif /* __HOLDOUT__ */ + + /* holdout mask objects do not write data passes */ + kernel_write_data_passes(kg, buffer, L, sd, state, throughput); + + /* blurring of bsdf after bounces, for rays that have a small likelihood + * of following this particular path (diffuse, rough glossy) */ + if(kernel_data.integrator.filter_glossy != FLT_MAX) { + float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf; + + if(blur_pdf < 1.0f) { + float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; + shader_bsdf_blur(kg, sd, blur_roughness); + } + } + +#ifdef __EMISSION__ + /* emission */ + if(sd->flag & SD_EMISSION) { + float3 emission = indirect_primitive_emission(kg, sd, sd->ray_length, state->flag, state->ray_pdf); + path_radiance_accum_emission(L, state, throughput, emission); + } +#endif /* __EMISSION__ */ + + return true; +} + ccl_device_noinline void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, ShaderData *emission_sd, @@ -78,9 +366,7 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg, light_ray.P = ray_offset(sd->P, sd->Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -#endif /* __OBJECT_MOTION__ */ light_ray.dP = sd->dP; light_ray.dD = differential3_zero(); @@ -102,203 +388,46 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, ShaderData *emission_sd, Ray *ray, float3 throughput, - int num_samples, PathState *state, PathRadiance *L) { /* path iteration */ for(;;) { - /* intersect scene */ + /* Find intersection with objects in scene. */ Intersection isect; - uint visibility = path_state_ray_visibility(kg, state); - if(state->bounce > kernel_data.integrator.ao_bounces) { - visibility = PATH_RAY_SHADOW; - ray->t = kernel_data.background.ao_distance; - } - bool hit = scene_intersect(kg, - *ray, - visibility, - &isect, - NULL, - 0.0f, 0.0f); - -#ifdef __LAMP_MIS__ - if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) { - /* ray starting from previous non-transparent bounce */ - Ray light_ray; - - light_ray.P = ray->P - state->ray_t*ray->D; - state->ray_t += isect.t; - light_ray.D = ray->D; - light_ray.t = state->ray_t; - light_ray.time = ray->time; - light_ray.dD = ray->dD; - light_ray.dP = ray->dP; - - /* intersect with lamp */ - float3 emission; - if(indirect_lamp_emission(kg, emission_sd, state, &light_ray, &emission)) { - path_radiance_accum_emission(L, - throughput, - emission, - state->bounce); - } - } -#endif /* __LAMP_MIS__ */ - -#ifdef __VOLUME__ - /* Sanitize volume stack. */ - if(!hit) { - kernel_volume_clean_stack(kg, state->volume_stack); - } - /* volume attenuation, emission, scatter */ - if(state->volume_stack[0].shader != SHADER_NONE) { - Ray volume_ray = *ray; - volume_ray.t = (hit)? isect.t: FLT_MAX; - - bool heterogeneous = - volume_stack_is_heterogeneous(kg, - state->volume_stack); - -# ifdef __VOLUME_DECOUPLED__ - int sampling_method = - volume_stack_sampling_method(kg, - state->volume_stack); - bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, false, sampling_method); - - if(decoupled) { - /* cache steps along volume for repeated sampling */ - VolumeSegment volume_segment; - - shader_setup_from_volume(kg, - sd, - &volume_ray); - kernel_volume_decoupled_record(kg, - state, - &volume_ray, - sd, - &volume_segment, - heterogeneous); - - volume_segment.sampling_method = sampling_method; - - /* emission */ - if(volume_segment.closure_flag & SD_EMISSION) { - path_radiance_accum_emission(L, - throughput, - volume_segment.accum_emission, - state->bounce); - } - - /* scattering */ - VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED; - - if(volume_segment.closure_flag & SD_SCATTER) { - int all = kernel_data.integrator.sample_all_lights_indirect; - - /* direct light sampling */ - kernel_branched_path_volume_connect_light(kg, - sd, - emission_sd, - throughput, - state, - L, - all, - &volume_ray, - &volume_segment); - - /* indirect sample. if we use distance sampling and take just - * one sample for direct and indirect light, we could share - * this computation, but makes code a bit complex */ - float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE); - float rscatter = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE); - - result = kernel_volume_decoupled_scatter(kg, - state, - &volume_ray, - sd, - &throughput, - rphase, - rscatter, - &volume_segment, - NULL, - true); - } - - /* free cached steps */ - kernel_volume_decoupled_free(kg, &volume_segment); - - if(result == VOLUME_PATH_SCATTERED) { - if(kernel_path_volume_bounce(kg, - sd, - &throughput, - state, - L, - ray)) - { - continue; - } - else { - break; - } - } - else { - throughput *= volume_segment.accum_transmittance; - } - } - else -# endif /* __VOLUME_DECOUPLED__ */ - { - /* integrate along volume segment with distance sampling */ - VolumeIntegrateResult result = kernel_volume_integrate( - kg, state, sd, &volume_ray, L, &throughput, heterogeneous); - -# ifdef __VOLUME_SCATTER__ - if(result == VOLUME_PATH_SCATTERED) { - /* direct lighting */ - kernel_path_volume_connect_light(kg, - sd, - emission_sd, - throughput, - state, - L); - - /* indirect light bounce */ - if(kernel_path_volume_bounce(kg, - sd, - &throughput, - state, - L, - ray)) - { - continue; - } - else { - break; - } - } -# endif /* __VOLUME_SCATTER__ */ - } + bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L); + + /* Find intersection with lamps and compute emission for MIS. */ + kernel_path_lamp_emission(kg, state, ray, throughput, &isect, emission_sd, L); + + /* Volume integration. */ + VolumeIntegrateResult result = kernel_path_volume(kg, + sd, + state, + ray, + &throughput, + &isect, + hit, + emission_sd, + L); + + if(result == VOLUME_PATH_SCATTERED) { + continue; + } + else if(result == VOLUME_PATH_MISSED) { + break; } -#endif /* __VOLUME__ */ + /* Shade background. */ if(!hit) { -#ifdef __BACKGROUND__ - /* sample background shader */ - float3 L_background = indirect_background(kg, emission_sd, state, ray); - path_radiance_accum_background(L, - state, - throughput, - L_background); -#endif /* __BACKGROUND__ */ - + kernel_path_background(kg, state, ray, throughput, emission_sd, L); break; } - else if(state->bounce > kernel_data.integrator.ao_bounces) { + else if(path_state_ao_bounce(kg, state)) { break; } - /* setup shading */ + /* Setup and evaluate shader. */ shader_setup_from_ray(kg, sd, &isect, @@ -309,46 +438,23 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, shader_merge_closures(sd); #endif /* __BRANCHED_PATH__ */ -#ifdef __SHADOW_TRICKS__ - if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER) && - (state->flag & PATH_RAY_SHADOW_CATCHER)) + /* Apply shadow catcher, holdout, emission. */ + if(!kernel_path_shader_apply(kg, + sd, + state, + ray, + throughput, + emission_sd, + L, + NULL)) { - /* Only update transparency after shadow catcher bounce. */ - L->shadow_transparency *= - average(shader_bsdf_transparency(kg, sd)); - } -#endif /* __SHADOW_TRICKS__ */ - - /* blurring of bsdf after bounces, for rays that have a small likelihood - * of following this particular path (diffuse, rough glossy) */ - if(kernel_data.integrator.filter_glossy != FLT_MAX) { - float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf; - - if(blur_pdf < 1.0f) { - float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; - shader_bsdf_blur(kg, sd, blur_roughness); - } - } - -#ifdef __EMISSION__ - /* emission */ - if(sd->flag & SD_EMISSION) { - float3 emission = indirect_primitive_emission(kg, - sd, - isect.t, - state->flag, - state->ray_pdf); - path_radiance_accum_emission(L, throughput, emission, state->bounce); + break; } -#endif /* __EMISSION__ */ /* path termination. this is a strange place to put the termination, it's * mainly due to the mixed in MIS that we use. gives too many unneeded * shader evaluations, only need emission if we are going to terminate */ - float probability = - path_state_continuation_probability(kg, - state, - throughput*num_samples); + float probability = path_state_continuation_probability(kg, state, throughput); if(probability == 0.0f) { break; @@ -424,26 +530,17 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, #endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */ -ccl_device_inline void kernel_path_integrate(KernelGlobals *kg, - uint rng_hash, - int sample, - Ray ray, - ccl_global float *buffer, - PathRadiance *L, - bool *is_shadow_catcher) +ccl_device_forceinline void kernel_path_integrate( + KernelGlobals *kg, + PathState *state, + float3 throughput, + Ray *ray, + PathRadiance *L, + ccl_global float *buffer, + ShaderData *emission_sd) { - /* initialize */ - float3 throughput = make_float3(1.0f, 1.0f, 1.0f); - - path_radiance_init(L, kernel_data.film.use_light_pass); - - /* shader data memory used for both volumes and surfaces, saves stack space */ + /* Shader data memory used for both volumes and surfaces, saves stack space. */ ShaderData sd; - /* shader data used by emission, shadows, volume stacks */ - ShaderData emission_sd; - - PathState state; - path_state_init(kg, &emission_sd, &state, rng_hash, sample, &ray); #ifdef __SUBSURFACE__ SubsurfaceIndirectRays ss_indirect; @@ -454,270 +551,80 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg, /* path iteration */ for(;;) { - /* intersect scene */ + /* Find intersection with objects in scene. */ Intersection isect; - uint visibility = path_state_ray_visibility(kg, &state); - -#ifdef __HAIR__ - float difl = 0.0f, extmax = 0.0f; - uint lcg_state = 0; - - if(kernel_data.bvh.have_curves) { - if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) { - float3 pixdiff = ray.dD.dx + ray.dD.dy; - /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/ - difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f; - } - - extmax = kernel_data.curve.maximum_width; - lcg_state = lcg_state_init(&state, 0x51633e2d); - } - - if(state.bounce > kernel_data.integrator.ao_bounces) { - visibility = PATH_RAY_SHADOW; - ray.t = kernel_data.background.ao_distance; - } - - bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax); -#else - bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f); -#endif /* __HAIR__ */ - -#ifdef __KERNEL_DEBUG__ - if(state.flag & PATH_RAY_CAMERA) { - L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes; - L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances; - L->debug_data.num_bvh_intersections += isect.num_intersections; - } - L->debug_data.num_ray_bounces++; -#endif /* __KERNEL_DEBUG__ */ - -#ifdef __LAMP_MIS__ - if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) { - /* ray starting from previous non-transparent bounce */ - Ray light_ray; - - light_ray.P = ray.P - state.ray_t*ray.D; - state.ray_t += isect.t; - light_ray.D = ray.D; - light_ray.t = state.ray_t; - light_ray.time = ray.time; - light_ray.dD = ray.dD; - light_ray.dP = ray.dP; - - /* intersect with lamp */ - float3 emission; - - if(indirect_lamp_emission(kg, &emission_sd, &state, &light_ray, &emission)) - path_radiance_accum_emission(L, throughput, emission, state.bounce); - } -#endif /* __LAMP_MIS__ */ - -#ifdef __VOLUME__ - /* Sanitize volume stack. */ - if(!hit) { - kernel_volume_clean_stack(kg, state.volume_stack); - } - /* volume attenuation, emission, scatter */ - if(state.volume_stack[0].shader != SHADER_NONE) { - Ray volume_ray = ray; - volume_ray.t = (hit)? isect.t: FLT_MAX; - - bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack); - -# ifdef __VOLUME_DECOUPLED__ - int sampling_method = volume_stack_sampling_method(kg, state.volume_stack); - bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true, sampling_method); - - if(decoupled) { - /* cache steps along volume for repeated sampling */ - VolumeSegment volume_segment; - - shader_setup_from_volume(kg, &sd, &volume_ray); - kernel_volume_decoupled_record(kg, &state, - &volume_ray, &sd, &volume_segment, heterogeneous); - - volume_segment.sampling_method = sampling_method; - - /* emission */ - if(volume_segment.closure_flag & SD_EMISSION) - path_radiance_accum_emission(L, throughput, volume_segment.accum_emission, state.bounce); - - /* scattering */ - VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED; - - if(volume_segment.closure_flag & SD_SCATTER) { - int all = false; - - /* direct light sampling */ - kernel_branched_path_volume_connect_light(kg, &sd, - &emission_sd, throughput, &state, L, all, - &volume_ray, &volume_segment); - - /* indirect sample. if we use distance sampling and take just - * one sample for direct and indirect light, we could share - * this computation, but makes code a bit complex */ - float rphase = path_state_rng_1D_for_decision(kg, &state, PRNG_PHASE); - float rscatter = path_state_rng_1D_for_decision(kg, &state, PRNG_SCATTER_DISTANCE); - - result = kernel_volume_decoupled_scatter(kg, - &state, &volume_ray, &sd, &throughput, - rphase, rscatter, &volume_segment, NULL, true); - } - - /* free cached steps */ - kernel_volume_decoupled_free(kg, &volume_segment); - - if(result == VOLUME_PATH_SCATTERED) { - if(kernel_path_volume_bounce(kg, &sd, &throughput, &state, L, &ray)) - continue; - else - break; - } - else { - throughput *= volume_segment.accum_transmittance; - } - } - else -# endif /* __VOLUME_DECOUPLED__ */ - { - /* integrate along volume segment with distance sampling */ - VolumeIntegrateResult result = kernel_volume_integrate( - kg, &state, &sd, &volume_ray, L, &throughput, heterogeneous); - -# ifdef __VOLUME_SCATTER__ - if(result == VOLUME_PATH_SCATTERED) { - /* direct lighting */ - kernel_path_volume_connect_light(kg, &sd, &emission_sd, throughput, &state, L); - - /* indirect light bounce */ - if(kernel_path_volume_bounce(kg, &sd, &throughput, &state, L, &ray)) - continue; - else - break; - } -# endif /* __VOLUME_SCATTER__ */ - } + bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L); + + /* Find intersection with lamps and compute emission for MIS. */ + kernel_path_lamp_emission(kg, state, ray, throughput, &isect, emission_sd, L); + + /* Volume integration. */ + VolumeIntegrateResult result = kernel_path_volume(kg, + &sd, + state, + ray, + &throughput, + &isect, + hit, + emission_sd, + L); + + if(result == VOLUME_PATH_SCATTERED) { + continue; + } + else if(result == VOLUME_PATH_MISSED) { + break; } -#endif /* __VOLUME__ */ + /* Shade background. */ if(!hit) { - /* eval background shader if nothing hit */ - if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) { - L->transparent += average(throughput); - -#ifdef __PASSES__ - if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) -#endif /* __PASSES__ */ - break; - } - -#ifdef __BACKGROUND__ - /* sample background shader */ - float3 L_background = indirect_background(kg, &emission_sd, &state, &ray); - path_radiance_accum_background(L, &state, throughput, L_background); -#endif /* __BACKGROUND__ */ - + kernel_path_background(kg, state, ray, throughput, emission_sd, L); break; } - else if(state.bounce > kernel_data.integrator.ao_bounces) { + else if(path_state_ao_bounce(kg, state)) { break; } - /* setup shading */ - shader_setup_from_ray(kg, &sd, &isect, &ray); - float rbsdf = path_state_rng_1D_for_decision(kg, &state, PRNG_BSDF); - shader_eval_surface(kg, &sd, &state, rbsdf, state.flag); - -#ifdef __SHADOW_TRICKS__ - if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { - if(state.flag & PATH_RAY_CAMERA) { - state.flag |= (PATH_RAY_SHADOW_CATCHER | - PATH_RAY_STORE_SHADOW_INFO); - if(!kernel_data.background.transparent) { - L->shadow_background_color = - indirect_background(kg, &emission_sd, &state, &ray); - } - L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L); - L->shadow_throughput = average(throughput); - } - } - else if(state.flag & PATH_RAY_SHADOW_CATCHER) { - /* Only update transparency after shadow catcher bounce. */ - L->shadow_transparency *= - average(shader_bsdf_transparency(kg, &sd)); - } -#endif /* __SHADOW_TRICKS__ */ - - /* holdout */ -#ifdef __HOLDOUT__ - if(((sd.flag & SD_HOLDOUT) || - (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) && - (state.flag & PATH_RAY_CAMERA)) + /* Setup and evaluate shader. */ + shader_setup_from_ray(kg, &sd, &isect, ray); + float rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF); + shader_eval_surface(kg, &sd, state, rbsdf, state->flag); + + /* Apply shadow catcher, holdout, emission. */ + if(!kernel_path_shader_apply(kg, + &sd, + state, + ray, + throughput, + emission_sd, + L, + buffer)) { - if(kernel_data.background.transparent) { - float3 holdout_weight; - if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) { - holdout_weight = make_float3(1.0f, 1.0f, 1.0f); - } - else { - holdout_weight = shader_holdout_eval(kg, &sd); - } - /* any throughput is ok, should all be identical here */ - L->transparent += average(holdout_weight*throughput); - } - - if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) { - break; - } - } -#endif /* __HOLDOUT__ */ - - /* holdout mask objects do not write data passes */ - kernel_write_data_passes(kg, buffer, L, &sd, sample, &state, throughput); - - /* blurring of bsdf after bounces, for rays that have a small likelihood - * of following this particular path (diffuse, rough glossy) */ - if(kernel_data.integrator.filter_glossy != FLT_MAX) { - float blur_pdf = kernel_data.integrator.filter_glossy*state.min_ray_pdf; - - if(blur_pdf < 1.0f) { - float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; - shader_bsdf_blur(kg, &sd, blur_roughness); - } - } - -#ifdef __EMISSION__ - /* emission */ - if(sd.flag & SD_EMISSION) { - /* todo: is isect.t wrong here for transparent surfaces? */ - float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf); - path_radiance_accum_emission(L, throughput, emission, state.bounce); + break; } -#endif /* __EMISSION__ */ /* path termination. this is a strange place to put the termination, it's * mainly due to the mixed in MIS that we use. gives too many unneeded * shader evaluations, only need emission if we are going to terminate */ - float probability = path_state_continuation_probability(kg, &state, throughput); + float probability = path_state_continuation_probability(kg, state, throughput); if(probability == 0.0f) { break; } else if(probability != 1.0f) { - float terminate = path_state_rng_1D_for_decision(kg, &state, PRNG_TERMINATE); + float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE); if(terminate >= probability) break; throughput /= probability; } - kernel_update_denoising_features(kg, &sd, &state, L); + kernel_update_denoising_features(kg, &sd, state, L); #ifdef __AO__ /* ambient occlusion */ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { - kernel_path_ao(kg, &sd, &emission_sd, L, &state, throughput, shader_bsdf_alpha(kg, &sd)); + kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd)); } #endif /* __AO__ */ @@ -727,10 +634,10 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg, if(sd.flag & SD_BSSRDF) { if(kernel_path_subsurface_scatter(kg, &sd, - &emission_sd, + emission_sd, L, - &state, - &ray, + state, + ray, &throughput, &ss_indirect)) { @@ -740,10 +647,10 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg, #endif /* __SUBSURFACE__ */ /* direct lighting */ - kernel_path_surface_connect_light(kg, &sd, &emission_sd, throughput, &state, L); + kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L); /* compute direct lighting and next bounce */ - if(!kernel_path_surface_bounce(kg, &sd, &throughput, &state, L, &ray)) + if(!kernel_path_surface_bounce(kg, &sd, &throughput, state, L, ray)) break; } @@ -756,8 +663,8 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg, if(ss_indirect.num_rays) { kernel_path_subsurface_setup_indirect(kg, &ss_indirect, - &state, - &ray, + state, + ray, L, &throughput); } @@ -766,10 +673,6 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg, } } #endif /* __SUBSURFACE__ */ - -#ifdef __SHADOW_TRICKS__ - *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER) != 0; -#endif /* __SHADOW_TRICKS__ */ } ccl_device void kernel_path_trace(KernelGlobals *kg, @@ -783,23 +686,37 @@ ccl_device void kernel_path_trace(KernelGlobals *kg, rng_state += index; buffer += index*pass_stride; - /* initialize random numbers and ray */ + /* Initialize random numbers and sample ray. */ uint rng_hash; Ray ray; kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng_hash, &ray); - /* integrate */ + if(ray.t == 0.0f) { + kernel_write_result(kg, buffer, sample, NULL); + return; + } + + /* Initialize state. */ + float3 throughput = make_float3(1.0f, 1.0f, 1.0f); + PathRadiance L; - bool is_shadow_catcher; + path_radiance_init(&L, kernel_data.film.use_light_pass); - if(ray.t != 0.0f) { - kernel_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher); - kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher); - } - else { - kernel_write_result(kg, buffer, sample, NULL, false); - } + ShaderData emission_sd; + PathState state; + path_state_init(kg, &emission_sd, &state, rng_hash, sample, &ray); + + /* Integrate. */ + kernel_path_integrate(kg, + &state, + throughput, + &ray, + &L, + buffer, + &emission_sd); + + kernel_write_result(kg, buffer, sample, &L); } #endif /* __SPLIT_KERNEL__ */ diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index dde40674ee6..3994d8d4954 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -48,9 +48,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg, light_ray.P = ray_offset(sd->P, sd->Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -#endif /* __OBJECT_MOTION__ */ light_ray.dP = sd->dP; light_ray.dD = differential3_zero(); @@ -144,7 +142,6 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba emission_sd, &bsdf_ray, tp*num_samples_inv, - num_samples, &ps, L); @@ -271,8 +268,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, int sample, Ray ray, ccl_global float *buffer, - PathRadiance *L, - bool *is_shadow_catcher) + PathRadiance *L) { /* initialize */ float3 throughput = make_float3(1.0f, 1.0f, 1.0f); @@ -292,36 +288,9 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, * Indirect bounces are handled in kernel_branched_path_surface_indirect_light(). */ for(;;) { - /* intersect scene */ + /* Find intersection with objects in scene. */ Intersection isect; - uint visibility = path_state_ray_visibility(kg, &state); - -#ifdef __HAIR__ - float difl = 0.0f, extmax = 0.0f; - uint lcg_state = 0; - - if(kernel_data.bvh.have_curves) { - if(kernel_data.cam.resolution == 1) { - float3 pixdiff = ray.dD.dx + ray.dD.dy; - /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/ - difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f; - } - - extmax = kernel_data.curve.maximum_width; - lcg_state = lcg_state_init(&state, 0x51633e2d); - } - - bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax); -#else - bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f); -#endif /* __HAIR__ */ - -#ifdef __KERNEL_DEBUG__ - L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes; - L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances; - L->debug_data.num_bvh_intersections += isect.num_intersections; - L->debug_data.num_ray_bounces++; -#endif /* __KERNEL_DEBUG__ */ + bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L); #ifdef __VOLUME__ /* Sanitize volume stack. */ @@ -376,10 +345,8 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, &ps, &pray, &sd, &tp, rphase, rscatter, &volume_segment, NULL, false); - (void)result; - kernel_assert(result == VOLUME_PATH_SCATTERED); - - if(kernel_path_volume_bounce(kg, + if(result == VOLUME_PATH_SCATTERED && + kernel_path_volume_bounce(kg, &sd, &tp, &ps, @@ -391,7 +358,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, &emission_sd, &pray, tp*num_samples_inv, - num_samples, &ps, L); @@ -405,7 +371,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, /* emission and transmittance */ if(volume_segment.closure_flag & SD_EMISSION) - path_radiance_accum_emission(L, throughput, volume_segment.accum_emission, state.bounce); + path_radiance_accum_emission(L, &state, throughput, volume_segment.accum_emission); throughput *= volume_segment.accum_transmittance; /* free cached steps */ @@ -447,7 +413,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, &emission_sd, &pray, tp, - num_samples, &ps, L); @@ -466,79 +431,29 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, } #endif /* __VOLUME__ */ + /* Shade background. */ if(!hit) { - /* eval background shader if nothing hit */ - if(kernel_data.background.transparent) { - L->transparent += average(throughput); - -#ifdef __PASSES__ - if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) -#endif /* __PASSES__ */ - break; - } - -#ifdef __BACKGROUND__ - /* sample background shader */ - float3 L_background = indirect_background(kg, &emission_sd, &state, &ray); - path_radiance_accum_background(L, &state, throughput, L_background); -#endif /* __BACKGROUND__ */ - + kernel_path_background(kg, &state, &ray, throughput, &emission_sd, L); break; } - /* setup shading */ + /* Setup and evaluate shader. */ shader_setup_from_ray(kg, &sd, &isect, &ray); shader_eval_surface(kg, &sd, &state, 0.0f, state.flag); shader_merge_closures(&sd); -#ifdef __SHADOW_TRICKS__ - if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { - state.flag |= (PATH_RAY_SHADOW_CATCHER | - PATH_RAY_STORE_SHADOW_INFO); - if(!kernel_data.background.transparent) { - L->shadow_background_color = - indirect_background(kg, &emission_sd, &state, &ray); - } - L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L); - L->shadow_throughput = average(throughput); - } - else if(state.flag & PATH_RAY_SHADOW_CATCHER) { - /* Only update transparency after shadow catcher bounce. */ - L->shadow_transparency *= - average(shader_bsdf_transparency(kg, &sd)); - } -#endif /* __SHADOW_TRICKS__ */ - - /* holdout */ -#ifdef __HOLDOUT__ - if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) { - if(kernel_data.background.transparent) { - float3 holdout_weight; - if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) { - holdout_weight = make_float3(1.0f, 1.0f, 1.0f); - } - else { - holdout_weight = shader_holdout_eval(kg, &sd); - } - /* any throughput is ok, should all be identical here */ - L->transparent += average(holdout_weight*throughput); - } - if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) { - break; - } - } -#endif /* __HOLDOUT__ */ - - /* holdout mask objects do not write data passes */ - kernel_write_data_passes(kg, buffer, L, &sd, sample, &state, throughput); - -#ifdef __EMISSION__ - /* emission */ - if(sd.flag & SD_EMISSION) { - float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf); - path_radiance_accum_emission(L, throughput, emission, state.bounce); + /* Apply shadow catcher, holdout, emission. */ + if(!kernel_path_shader_apply(kg, + &sd, + &state, + &ray, + throughput, + &emission_sd, + L, + buffer)) + { + break; } -#endif /* __EMISSION__ */ /* transparency termination */ if(state.flag & PATH_RAY_TRANSPARENT) { @@ -620,10 +535,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); #endif /* __VOLUME__ */ } - -#ifdef __SHADOW_TRICKS__ - *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER) != 0; -#endif /* __SHADOW_TRICKS__ */ } ccl_device void kernel_branched_path_trace(KernelGlobals *kg, @@ -645,14 +556,13 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg, /* integrate */ PathRadiance L; - bool is_shadow_catcher; if(ray.t != 0.0f) { - kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher); - kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher); + kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L); + kernel_write_result(kg, buffer, sample, &L); } else { - kernel_write_result(kg, buffer, sample, NULL, false); + kernel_write_result(kg, buffer, sample, NULL); } } diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index b539224db31..bb09b4ac080 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -29,6 +29,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, state->rng_offset = PRNG_BASE_NUM; state->sample = sample; state->num_samples = kernel_data.integrator.aa_samples; + state->branch_factor = 1.0f; state->bounce = 0; state->diffuse_bounce = 0; @@ -143,7 +144,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta #endif } -ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state) +ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, ccl_addr_space PathState *state) { uint flag = state->flag & PATH_RAY_ALL_VISIBILITY; @@ -157,7 +158,9 @@ ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *s return flag; } -ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput) +ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, + ccl_addr_space PathState *state, + const float3 throughput) { if(state->flag & PATH_RAY_TRANSPARENT) { /* Transparent rays are treated separately with own max bounces. */ @@ -201,7 +204,7 @@ ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, c /* Probalistic termination: use sqrt() to roughly match typical view * transform and do path termination a bit later on average. */ - return sqrtf(max3(fabs(throughput))); + return min(sqrtf(max3(fabs(throughput)) * state->branch_factor), 1.0f); } /* TODO(DingTo): Find more meaningful name for this */ @@ -214,5 +217,30 @@ ccl_device_inline void path_state_modify_bounce(ccl_addr_space PathState *state, state->bounce -= 1; } +ccl_device_inline bool path_state_ao_bounce(KernelGlobals *kg, ccl_addr_space PathState *state) +{ + if(state->bounce <= kernel_data.integrator.ao_bounces) { + return false; + } + + int bounce = state->bounce - state->transmission_bounce - (state->glossy_bounce > 0); + return (bounce > kernel_data.integrator.ao_bounces); +} + +ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, + int branch, + int num_branches) +{ + state->rng_offset += PRNG_BOUNCE_NUM; + + if(num_branches > 1) { + /* Path is splitting into a branch, adjust so that each branch + * still gets a unique sample from the same sequence. */ + state->sample = state->sample*num_branches + branch; + state->num_samples = state->num_samples*num_branches; + state->branch_factor *= num_branches; + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h index 9bccc9201e0..619d57e71fb 100644 --- a/intern/cycles/kernel/kernel_path_subsurface.h +++ b/intern/cycles/kernel/kernel_path_subsurface.h @@ -124,7 +124,7 @@ bool kernel_path_subsurface_scatter( ss_indirect->num_rays++; } else { - path_radiance_accum_sample(L, hit_L, 1); + path_radiance_accum_sample(L, hit_L); } } return true; @@ -145,7 +145,7 @@ ccl_device void kernel_path_subsurface_accum_indirect( { if(ss_indirect->tracing) { path_radiance_sum_indirect(L); - path_radiance_accum_sample(&ss_indirect->direct_L, L, 1); + path_radiance_accum_sample(&ss_indirect->direct_L, L); if(ss_indirect->num_rays == 0) { *L = ss_indirect->direct_L; } diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 6c3a444e48a..e798fcc6a2c 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -85,17 +85,16 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light( float num_samples_inv = num_samples_adjust/num_samples; for(int j = 0; j < num_samples; j++) { - float light_t = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT); float light_u, light_v; path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples); /* only sample triangle lights */ if(kernel_data.integrator.num_all_lights) - light_t = 0.5f*light_t; + light_u = 0.5f*light_u; LightSample ls; - if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { /* Same as above, probability needs to be corrected since the sampling was forced to select a mesh light. */ if(kernel_data.integrator.num_all_lights) ls.pdf *= 2.0f; @@ -118,13 +117,12 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light( } else { /* sample one light at random */ - float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT); float light_u, light_v; path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); float terminate = path_state_rng_light_termination(kg, state); LightSample ls; - if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { /* sample random light */ if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { /* trace shadow ray */ @@ -238,7 +236,6 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, #endif /* sample illumination from lights to find path contribution */ - float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT); float light_u, light_v; path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); @@ -251,7 +248,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, #endif LightSample ls; - if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { float terminate = path_state_rng_light_termination(kg, state); if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { /* trace shadow ray */ diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h index c9c7f447c42..e7e24f853c2 100644 --- a/intern/cycles/kernel/kernel_path_volume.h +++ b/intern/cycles/kernel/kernel_path_volume.h @@ -31,7 +31,6 @@ ccl_device_inline void kernel_path_volume_connect_light( return; /* sample illumination from lights to find path contribution */ - float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT); float light_u, light_v; path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); @@ -41,11 +40,9 @@ ccl_device_inline void kernel_path_volume_connect_light( bool is_lamp; /* connect to light from given point where shader has been evaluated */ -# ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -# endif - if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) + if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { float terminate = path_state_rng_light_termination(kg, state); if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { @@ -135,9 +132,7 @@ ccl_device void kernel_branched_path_volume_connect_light( BsdfEval L_light; bool is_lamp; -# ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -# endif if(sample_all_lights) { /* lamp sampling */ @@ -166,11 +161,9 @@ ccl_device void kernel_branched_path_volume_connect_light( VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false); - (void)result; - kernel_assert(result == VOLUME_PATH_SCATTERED); - /* todo: split up light_sample so we don't have to call it again with new position */ - if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) { + if(result == VOLUME_PATH_SCATTERED && + lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) { if(kernel_data.integrator.pdf_triangles != 0.0f) ls.pdf *= 2.0f; @@ -195,16 +188,15 @@ ccl_device void kernel_branched_path_volume_connect_light( for(int j = 0; j < num_samples; j++) { /* sample random position on random triangle */ - float light_t = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT); float light_u, light_v; path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); /* only sample triangle lights */ if(kernel_data.integrator.num_all_lights) - light_t = 0.5f*light_t; + light_u = 0.5f*light_u; LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls); + light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls); float3 tp = throughput; @@ -215,11 +207,9 @@ ccl_device void kernel_branched_path_volume_connect_light( VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false); - (void)result; - kernel_assert(result == VOLUME_PATH_SCATTERED); - /* todo: split up light_sample so we don't have to call it again with new position */ - if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if(result == VOLUME_PATH_SCATTERED && + light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { if(kernel_data.integrator.num_all_lights) ls.pdf *= 2.0f; @@ -239,12 +229,11 @@ ccl_device void kernel_branched_path_volume_connect_light( } else { /* sample random position on random light */ - float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT); float light_u, light_v; path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls); + light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls); float3 tp = throughput; @@ -255,11 +244,9 @@ ccl_device void kernel_branched_path_volume_connect_light( VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false); - (void)result; - kernel_assert(result == VOLUME_PATH_SCATTERED); - /* todo: split up light_sample so we don't have to call it again with new position */ - if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if(result == VOLUME_PATH_SCATTERED && + light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { /* sample random light */ float terminate = path_state_rng_light_termination(kg, state); if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 221d92f5de1..b35ed3bd279 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -296,17 +296,6 @@ ccl_device_inline float path_branched_rng_light_termination( return 0.0f; } -ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, - int branch, - int num_branches) -{ - /* path is splitting into a branch, adjust so that each branch - * still gets a unique sample from the same sequence */ - state->rng_offset += PRNG_BOUNCE_NUM; - state->sample = state->sample*num_branches + branch; - state->num_samples = state->num_samples*num_branches; -} - ccl_device_inline uint lcg_state_init(PathState *state, uint scramble) { diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index dd64f5b05ba..5964aca0c78 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -66,8 +66,8 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg, /* matrices and time */ #ifdef __OBJECT_MOTION__ shader_setup_object_transforms(kg, sd, ray->time); - sd->time = ray->time; #endif + sd->time = ray->time; sd->prim = kernel_tex_fetch(__prim_index, isect->prim); sd->ray_length = isect->t; @@ -271,17 +271,17 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg, sd->u = u; sd->v = v; #endif + sd->time = time; sd->ray_length = t; sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); sd->object_flag = 0; if(sd->object != OBJECT_NONE) { sd->object_flag |= kernel_tex_fetch(__object_flag, - sd->object); + sd->object); #ifdef __OBJECT_MOTION__ shader_setup_object_transforms(kg, sd, time); - sd->time = time; } else if(lamp != LAMP_NONE) { sd->ob_tfm = lamp_fetch_transform(kg, lamp, false); @@ -385,9 +385,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat sd->shader = kernel_data.background.surface_shader; sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); sd->object_flag = 0; -#ifdef __OBJECT_MOTION__ sd->time = ray->time; -#endif sd->ray_length = 0.0f; #ifdef __INSTANCING__ @@ -427,9 +425,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s sd->shader = SHADER_NONE; sd->flag = 0; sd->object_flag = 0; -#ifdef __OBJECT_MOTION__ sd->time = ray->time; -#endif sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */ #ifdef __INSTANCING__ diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index 22e085e94da..3a534bbb6be 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -16,6 +16,39 @@ CCL_NAMESPACE_BEGIN +#ifdef __VOLUME__ +typedef struct VolumeState { +# ifdef __SPLIT_KERNEL__ +# else + PathState ps; +# endif +} VolumeState; + +/* Get PathState ready for use for volume stack evaluation. */ +ccl_device_inline PathState *shadow_blocked_volume_path_state( + KernelGlobals *kg, + VolumeState *volume_state, + ccl_addr_space PathState *state, + ShaderData *sd, + Ray *ray) +{ +# ifdef __SPLIT_KERNEL__ + ccl_addr_space PathState *ps = + &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)]; +# else + PathState *ps = &volume_state->ps; +# endif + *ps = *state; + /* We are checking for shadow on the "other" side of the surface, so need + * to discard volume we are currently at. + */ + if(dot(sd->Ng, ray->D) < 0.0f) { + kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack); + } + return ps; +} +#endif /* __VOLUME__ */ + /* Attenuate throughput accordingly to the given intersection event. * Returns true if the throughput is zero and traversal can be aborted. */ @@ -119,39 +152,6 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg, # define SHADOW_STACK_MAX_HITS 64 -# ifdef __VOLUME__ -struct VolumeState { -# ifdef __SPLIT_KERNEL__ -# else - PathState ps; -# endif -}; - -/* Get PathState ready for use for volume stack evaluation. */ -ccl_device_inline PathState *shadow_blocked_volume_path_state( - KernelGlobals *kg, - VolumeState *volume_state, - ccl_addr_space PathState *state, - ShaderData *sd, - Ray *ray) -{ -# ifdef __SPLIT_KERNEL__ - ccl_addr_space PathState *ps = - &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)]; -# else - PathState *ps = &volume_state->ps; -# endif - *ps = *state; - /* We are checking for shadow on the "other" side of the surface, so need - * to discard volume we are currently at. - */ - if(dot(sd->Ng, ray->D) < 0.0f) { - kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack); - } - return ps; -} -#endif // __VOLUME__ - /* Actual logic with traversal loop implementation which is free from device * specific tweaks. * diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 8f65c00491c..1b4e926ca28 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -292,7 +292,7 @@ enum PathTraceDimension { PRNG_BSDF_U = 0, PRNG_BSDF_V = 1, PRNG_BSDF = 2, - PRNG_LIGHT = 3, + PRNG_UNUSED3 = 3, PRNG_LIGHT_U = 4, PRNG_LIGHT_V = 5, PRNG_LIGHT_TERMINATE = 6, @@ -535,11 +535,13 @@ typedef ccl_addr_space struct PathRadiance { /* Path radiance sum and throughput at the moment when ray hits shadow * catcher object. */ - float3 shadow_radiance_sum; float shadow_throughput; /* Accumulated transparency along the path after shadow catcher bounce. */ float shadow_transparency; + + /* Indicate if any shadow catcher data is set. */ + int has_shadow_catcher; #endif #ifdef __DENOISING_FEATURES__ @@ -1006,9 +1008,10 @@ typedef struct PathState { /* random number generator state */ uint rng_hash; /* per pixel hash */ - 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 sample; /* path sample number */ + int num_samples; /* total number of times this path will be sampled */ + float branch_factor; /* number of branches in indirect paths */ /* bounce counting */ int bounce; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 42094a9c3f8..d8e8e192ab2 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -438,7 +438,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous( float3 sigma_t = coeff.sigma_a + coeff.sigma_s; float3 transmittance = volume_color_transmittance(sigma_t, ray->t); float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, ray->t); - path_radiance_accum_emission(L, *throughput, emission, state->bounce); + path_radiance_accum_emission(L, state, *throughput, emission); } /* modify throughput */ @@ -558,7 +558,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance( /* integrate emission attenuated by absorption */ if(L && (closure_flag & SD_EMISSION)) { float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt); - path_radiance_accum_emission(L, tp, emission, state->bounce); + path_radiance_accum_emission(L, state, tp, emission); } /* modify throughput */ @@ -997,8 +997,8 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter( mis_weight = 2.0f*power_heuristic(pdf, distance_pdf); } } - if(sample_t < 1e-6f || pdf == 0.0f) { - return VOLUME_PATH_SCATTERED; + if(sample_t < 0.0f || pdf == 0.0f) { + return VOLUME_PATH_MISSED; } /* compute transmittance up to this step */ diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h index 9fe4ec18e9e..2c390593ba1 100644 --- a/intern/cycles/kernel/split/kernel_branched.h +++ b/intern/cycles/kernel/split/kernel_branched.h @@ -188,7 +188,6 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter( /* update state for next iteration */ branched_state->next_closure = i; branched_state->next_sample = j+1; - branched_state->num_samples = num_samples; /* start the indirect path */ *tp *= num_samples_inv; diff --git a/intern/cycles/kernel/split/kernel_buffer_update.h b/intern/cycles/kernel/split/kernel_buffer_update.h index 3b61319e349..7b4d1299c12 100644 --- a/intern/cycles/kernel/split/kernel_buffer_update.h +++ b/intern/cycles/kernel/split/kernel_buffer_update.h @@ -94,8 +94,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride; /* accumulate result in output buffer */ - bool is_shadow_catcher = (state->flag & PATH_RAY_SHADOW_CATCHER); - kernel_write_result(kg, buffer, sample, L, is_shadow_catcher); + kernel_write_result(kg, buffer, sample, L); ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE); } diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h index 8e3f7555550..2aac66ecb84 100644 --- a/intern/cycles/kernel/split/kernel_direct_lighting.h +++ b/intern/cycles/kernel/split/kernel_direct_lighting.h @@ -81,23 +81,20 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, if(flag) { /* Sample illumination from lights to find path contribution. */ - float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT); float light_u, light_v; path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); float terminate = path_state_rng_light_termination(kg, state); LightSample ls; if(light_sample(kg, - light_t, light_u, light_v, + light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { Ray light_ray; -# ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -# endif BsdfEval L_light; bool is_lamp; diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h index 478d83d633e..2975aa20004 100644 --- a/intern/cycles/kernel/split/kernel_do_volume.h +++ b/intern/cycles/kernel/split/kernel_do_volume.h @@ -72,7 +72,6 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K /* start the indirect path */ branched_state->next_closure = 0; branched_state->next_sample = j+1; - branched_state->num_samples = num_samples; /* Attempting to share too many samples is slow for volumes as it causes us to * loop here more and have many calls to kernel_volume_integrate which evaluates diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h index 253b78526e7..9036b1e473d 100644 --- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h +++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h @@ -94,161 +94,63 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( ccl_global PathState *state = 0x0; float3 throughput; - uint sample; ccl_global char *ray_state = kernel_split_state.ray_state; ShaderData *sd = &kernel_split_state.sd[ray_index]; - ccl_global float *buffer = kernel_split_params.buffer; if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { uint work_index = kernel_split_state.work_array[ray_index]; - sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample; - uint pixel_x, pixel_y, tile_x, tile_y; get_work_pixel_tile_position(kg, &pixel_x, &pixel_y, &tile_x, &tile_y, work_index, ray_index); + ccl_global float *buffer = kernel_split_params.buffer; buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride; + ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + throughput = kernel_split_state.throughput[ray_index]; state = &kernel_split_state.path_state[ray_index]; -#ifdef __SHADOW_TRICKS__ - if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { - if(state->flag & PATH_RAY_CAMERA) { - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - state->flag |= (PATH_RAY_SHADOW_CATCHER | - PATH_RAY_STORE_SHADOW_INFO); - if(!kernel_data.background.transparent) { - ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - L->shadow_background_color = indirect_background( - kg, - &kernel_split_state.sd_DL_shadow[ray_index], - state, - ray); - } - L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L); - L->shadow_throughput = average(throughput); - } - } - else if(state->flag & PATH_RAY_SHADOW_CATCHER) { - /* Only update transparency after shadow catcher bounce. */ - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - L->shadow_transparency *= average(shader_bsdf_transparency(kg, sd)); - } -#endif /* __SHADOW_TRICKS__ */ - - /* holdout */ -#ifdef __HOLDOUT__ - if(((sd->flag & SD_HOLDOUT) || - (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) && - (state->flag & PATH_RAY_CAMERA)) + if(!kernel_path_shader_apply(kg, + sd, + state, + ray, + throughput, + emission_sd, + L, + buffer)) { - if(kernel_data.background.transparent) { - float3 holdout_weight; - if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { - holdout_weight = make_float3(1.0f, 1.0f, 1.0f); - } - else { - holdout_weight = shader_holdout_eval(kg, sd); - } - /* any throughput is ok, should all be identical here */ - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - L->transparent += average(holdout_weight*throughput); - } - if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { - kernel_split_path_end(kg, ray_index); - } + kernel_split_path_end(kg, ray_index); } -#endif /* __HOLDOUT__ */ } if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - -#ifdef __BRANCHED_PATH__ - if(!IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) -#endif /* __BRANCHED_PATH__ */ - { - /* Holdout mask objects do not write data passes. */ - kernel_write_data_passes(kg, - buffer, - L, - sd, - sample, - state, - throughput); - } - - /* Blurring of bsdf after bounces, for rays that have a small likelihood - * of following this particular path (diffuse, rough glossy. - */ -#ifndef __BRANCHED_PATH__ - if(kernel_data.integrator.filter_glossy != FLT_MAX) -#else - if(kernel_data.integrator.filter_glossy != FLT_MAX && - (!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT))) -#endif /* __BRANCHED_PATH__ */ - { - float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf; - if(blur_pdf < 1.0f) { - float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; - shader_bsdf_blur(kg, sd, blur_roughness); - } - } - -#ifdef __EMISSION__ - /* emission */ - if(sd->flag & SD_EMISSION) { - /* TODO(sergey): is isect.t wrong here for transparent surfaces? */ - float3 emission = indirect_primitive_emission( - kg, - sd, - kernel_split_state.isect[ray_index].t, - state->flag, - state->ray_pdf); - path_radiance_accum_emission(L, throughput, emission, state->bounce); - } -#endif /* __EMISSION__ */ - /* Path termination. this is a strange place to put the termination, it's * mainly due to the mixed in MIS that we use. gives too many unneeded * shader evaluations, only need emission if we are going to terminate. */ -#ifndef __BRANCHED_PATH__ float probability = path_state_continuation_probability(kg, state, throughput); -#else - float probability = 1.0f; - - if(!kernel_data.integrator.branched) { - probability = path_state_continuation_probability(kg, state, throughput); - } - else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { - int num_samples = kernel_split_state.branched_state[ray_index].num_samples; - probability = path_state_continuation_probability(kg, state, throughput*num_samples); - } - else if(state->flag & PATH_RAY_TRANSPARENT) { - probability = path_state_continuation_probability(kg, state, throughput); - } -#endif if(probability == 0.0f) { kernel_split_path_end(kg, ray_index); } - - if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { - if(probability != 1.0f) { - float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE); - if(terminate >= probability) { - kernel_split_path_end(kg, ray_index); - } - else { - kernel_split_state.throughput[ray_index] = throughput/probability; - } + else if(probability < 1.0f) { + float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE); + if(terminate >= probability) { + kernel_split_path_end(kg, ray_index); } + else { + kernel_split_state.throughput[ray_index] = throughput/probability; + } + } + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; kernel_update_denoising_features(kg, sd, state, L); } } diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h index 04d5769ef0d..437043a5971 100644 --- a/intern/cycles/kernel/split/kernel_indirect_background.h +++ b/intern/cycles/kernel/split/kernel_indirect_background.h @@ -33,7 +33,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg) if(ray_index != QUEUE_EMPTY_SLOT) { if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; - if(state->bounce > kernel_data.integrator.ao_bounces) { + if(path_state_ao_bounce(kg, state)) { kernel_split_path_end(kg, ray_index); } } @@ -50,32 +50,16 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg) return; } - ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; - if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { - /* eval background shader if nothing hit */ - if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) { - L->transparent += average((*throughput)); -#ifdef __PASSES__ - if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) -#endif - kernel_split_path_end(kg, ray_index); - } + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; + float3 throughput = kernel_split_state.throughput[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; - if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { -#ifdef __BACKGROUND__ - /* sample background shader */ - float3 L_background = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray); - path_radiance_accum_background(L, state, (*throughput), L_background); -#endif - kernel_split_path_end(kg, ray_index); - } + kernel_path_background(kg, state, ray, throughput, emission_sd, L); + kernel_split_path_end(kg, ray_index); } - - } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_lamp_emission.h b/intern/cycles/kernel/split/kernel_lamp_emission.h index c669d79ddcd..448456d167d 100644 --- a/intern/cycles/kernel/split/kernel_lamp_emission.h +++ b/intern/cycles/kernel/split/kernel_lamp_emission.h @@ -57,27 +57,10 @@ ccl_device void kernel_lamp_emission(KernelGlobals *kg) float3 throughput = kernel_split_state.throughput[ray_index]; Ray ray = kernel_split_state.ray[ray_index]; + ccl_global Intersection *isect = &kernel_split_state.isect[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; -#ifdef __LAMP_MIS__ - if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) { - /* ray starting from previous non-transparent bounce */ - Ray light_ray; - - light_ray.P = ray.P - state->ray_t*ray.D; - state->ray_t += kernel_split_state.isect[ray_index].t; - light_ray.D = ray.D; - light_ray.t = state->ray_t; - light_ray.time = ray.time; - light_ray.dD = ray.dD; - light_ray.dP = ray.dP; - /* intersect with lamp */ - float3 emission; - - if(indirect_lamp_emission(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &light_ray, &emission)) { - path_radiance_accum_emission(L, throughput, emission, state->bounce); - } - } -#endif /* __LAMP_MIS__ */ + kernel_path_lamp_emission(kg, state, &ray, throughput, isect, emission_sd, L); } } diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h index d0afd39ef29..f5378bc172b 100644 --- a/intern/cycles/kernel/split/kernel_scene_intersect.h +++ b/intern/cycles/kernel/split/kernel_scene_intersect.h @@ -59,49 +59,13 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg) return; } - Intersection isect; - PathState state = kernel_split_state.path_state[ray_index]; + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; Ray ray = kernel_split_state.ray[ray_index]; - - /* intersect scene */ - uint visibility = path_state_ray_visibility(kg, &state); - - if(state.bounce > kernel_data.integrator.ao_bounces) { - visibility = PATH_RAY_SHADOW; - ray.t = kernel_data.background.ao_distance; - } - -#ifdef __HAIR__ - float difl = 0.0f, extmax = 0.0f; - uint lcg_state = 0; - - if(kernel_data.bvh.have_curves) { - if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) { - float3 pixdiff = ray.dD.dx + ray.dD.dy; - /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/ - difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f; - } - - extmax = kernel_data.curve.maximum_width; - lcg_state = lcg_state_init(&state, 0x51633e2d); - } - - bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax); -#else - bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f); -#endif - kernel_split_state.isect[ray_index] = isect; - -#ifdef __KERNEL_DEBUG__ PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - if(state.flag & PATH_RAY_CAMERA) { - L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes; - L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances; - L->debug_data.num_bvh_intersections += isect.num_intersections; - } - L->debug_data.num_ray_bounces++; -#endif + Intersection isect; + bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L); + kernel_split_state.isect[ray_index] = isect; if(!hit) { /* Change the state of rays that hit the background; diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h index 08f0124b529..558d327bc76 100644 --- a/intern/cycles/kernel/split/kernel_split_common.h +++ b/intern/cycles/kernel/split/kernel_split_common.h @@ -63,7 +63,7 @@ ccl_device_inline void kernel_split_path_end(KernelGlobals *kg, int ray_index) PathRadiance *orig_ray_L = &kernel_split_state.path_radiance[orig_ray]; path_radiance_sum_indirect(L); - path_radiance_accum_sample(orig_ray_L, L, 1); + path_radiance_accum_sample(orig_ray_L, L); atomic_fetch_and_dec_uint32((ccl_global uint*)&kernel_split_state.branched_state[orig_ray].shared_sample_count); diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h index 3eae884d479..e08afc22b20 100644 --- a/intern/cycles/kernel/split/kernel_split_data_types.h +++ b/intern/cycles/kernel/split/kernel_split_data_types.h @@ -72,7 +72,6 @@ typedef ccl_global struct SplitBranchedState { /* indirect loop state */ int next_closure; int next_sample; - int num_samples; #ifdef __SUBSURFACE__ int ss_next_closure; |