Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernel_path_branched.h
| Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { | ||||
| light_ray.t = kernel_data.background.ao_distance; | light_ray.t = kernel_data.background.ao_distance; | ||||
| #ifdef __OBJECT_MOTION__ | #ifdef __OBJECT_MOTION__ | ||||
| light_ray.time = sd->time; | light_ray.time = sd->time; | ||||
| #endif /* __OBJECT_MOTION__ */ | #endif /* __OBJECT_MOTION__ */ | ||||
| light_ray.dP = sd->dP; | light_ray.dP = sd->dP; | ||||
| light_ray.dD = differential3_zero(); | light_ray.dD = differential3_zero(); | ||||
| if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) { | if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) { | ||||
| path_radiance_accum_ao(L, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce); | path_radiance_accum_ao(L, state, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow); | ||||
| } | } | ||||
| else { | else { | ||||
| path_radiance_accum_total_ao(L, throughput*num_samples_inv, ao_bsdf); | path_radiance_accum_total_ao(L, state, throughput*num_samples_inv, ao_bsdf); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* bounce off surface and integrate indirect light */ | /* bounce off surface and integrate indirect light */ | ||||
| ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg, | ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg, | ||||
| RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd, | RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd, | ||||
| float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L) | float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L) | ||||
| { | { | ||||
| float sum_sample_weight = 0.0f; | |||||
| #ifdef __DENOISING_FEATURES__ | |||||
| for(int i = 0; i < sd->num_closure; i++) { | |||||
| const ShaderClosure *sc = &sd->closure[i]; | |||||
| if(!CLOSURE_IS_BSDF(sc->type)) | |||||
| continue; | |||||
| /* transparency is not handled here, but in outer loop */ | |||||
| if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) | |||||
| continue; | |||||
| sum_sample_weight += sc->sample_weight; | |||||
| } | |||||
brecht: Can we only run this when denoising is enabled? | |||||
| #endif /* __DENOISING_FEATURES__ */ | |||||
| for(int i = 0; i < sd->num_closure; i++) { | for(int i = 0; i < sd->num_closure; i++) { | ||||
| const ShaderClosure *sc = &sd->closure[i]; | const ShaderClosure *sc = &sd->closure[i]; | ||||
| if(!CLOSURE_IS_BSDF(sc->type)) | if(!CLOSURE_IS_BSDF(sc->type)) | ||||
| continue; | continue; | ||||
| /* transparency is not handled here, but in outer loop */ | /* transparency is not handled here, but in outer loop */ | ||||
| if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) | if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) | ||||
| continue; | continue; | ||||
| Show All 23 Lines | for(int j = 0; j < num_samples; j++) { | ||||
| &bsdf_rng, | &bsdf_rng, | ||||
| sd, | sd, | ||||
| sc, | sc, | ||||
| j, | j, | ||||
| num_samples, | num_samples, | ||||
| &tp, | &tp, | ||||
| &ps, | &ps, | ||||
| L, | L, | ||||
| &bsdf_ray)) | &bsdf_ray, | ||||
| sum_sample_weight)) | |||||
| { | { | ||||
| continue; | continue; | ||||
| } | } | ||||
| kernel_path_indirect(kg, | kernel_path_indirect(kg, | ||||
| indirect_sd, | indirect_sd, | ||||
| emission_sd, | emission_sd, | ||||
| rng, | rng, | ||||
| ▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | #endif /* __EMISSION__ */ | ||||
| &hit_state, | &hit_state, | ||||
| L); | L); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif /* __SUBSURFACE__ */ | #endif /* __SUBSURFACE__ */ | ||||
| ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer) | ccl_device float kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer, PathRadiance *L, bool *is_shadow_catcher) | ||||
| { | { | ||||
| /* initialize */ | /* initialize */ | ||||
| PathRadiance L; | |||||
| float3 throughput = make_float3(1.0f, 1.0f, 1.0f); | float3 throughput = make_float3(1.0f, 1.0f, 1.0f); | ||||
| float L_transparent = 0.0f; | float L_transparent = 0.0f; | ||||
| path_radiance_init(&L, kernel_data.film.use_light_pass); | 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; | ShaderData sd; | ||||
| /* shader data used by emission, shadows, volume stacks, indirect path */ | /* shader data used by emission, shadows, volume stacks, indirect path */ | ||||
| ShaderData emission_sd, indirect_sd; | ShaderData emission_sd, indirect_sd; | ||||
| PathState state; | PathState state; | ||||
| path_state_init(kg, &emission_sd, &state, rng, sample, &ray); | path_state_init(kg, &emission_sd, &state, rng, sample, &ray); | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | #ifdef __VOLUME_DECOUPLED__ | ||||
| /* direct light sampling */ | /* direct light sampling */ | ||||
| if(volume_segment.closure_flag & SD_SCATTER) { | if(volume_segment.closure_flag & SD_SCATTER) { | ||||
| volume_segment.sampling_method = volume_stack_sampling_method(kg, state.volume_stack); | volume_segment.sampling_method = volume_stack_sampling_method(kg, state.volume_stack); | ||||
| int all = kernel_data.integrator.sample_all_lights_direct; | int all = kernel_data.integrator.sample_all_lights_direct; | ||||
| kernel_branched_path_volume_connect_light(kg, rng, &sd, | kernel_branched_path_volume_connect_light(kg, rng, &sd, | ||||
| &emission_sd, throughput, &state, &L, all, | &emission_sd, throughput, &state, L, all, | ||||
| &volume_ray, &volume_segment); | &volume_ray, &volume_segment); | ||||
| /* indirect light sampling */ | /* indirect light sampling */ | ||||
| int num_samples = kernel_data.integrator.volume_samples; | int num_samples = kernel_data.integrator.volume_samples; | ||||
| float num_samples_inv = 1.0f/num_samples; | float num_samples_inv = 1.0f/num_samples; | ||||
| for(int j = 0; j < num_samples; j++) { | for(int j = 0; j < num_samples; j++) { | ||||
| /* workaround to fix correlation bug in T38710, can find better solution | /* workaround to fix correlation bug in T38710, can find better solution | ||||
| Show All 20 Lines | #ifdef __VOLUME_DECOUPLED__ | ||||
| (void)result; | (void)result; | ||||
| kernel_assert(result == VOLUME_PATH_SCATTERED); | kernel_assert(result == VOLUME_PATH_SCATTERED); | ||||
| if(kernel_path_volume_bounce(kg, | if(kernel_path_volume_bounce(kg, | ||||
| rng, | rng, | ||||
| &sd, | &sd, | ||||
| &tp, | &tp, | ||||
| &ps, | &ps, | ||||
| &L, | L, | ||||
| &pray)) | &pray)) | ||||
| { | { | ||||
| kernel_path_indirect(kg, | kernel_path_indirect(kg, | ||||
| &indirect_sd, | &indirect_sd, | ||||
| &emission_sd, | &emission_sd, | ||||
| rng, | rng, | ||||
| &pray, | &pray, | ||||
| tp*num_samples_inv, | tp*num_samples_inv, | ||||
| num_samples, | num_samples, | ||||
| &ps, | &ps, | ||||
| &L); | L); | ||||
| /* for render passes, sum and reset indirect light pass variables | /* for render passes, sum and reset indirect light pass variables | ||||
| * for the next samples */ | * for the next samples */ | ||||
| path_radiance_sum_indirect(&L); | path_radiance_sum_indirect(L); | ||||
| path_radiance_reset_indirect(&L); | path_radiance_reset_indirect(L); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* emission and transmittance */ | /* emission and transmittance */ | ||||
| if(volume_segment.closure_flag & SD_EMISSION) | if(volume_segment.closure_flag & SD_EMISSION) | ||||
| path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce); | path_radiance_accum_emission(L, throughput, volume_segment.accum_emission, state.bounce); | ||||
| throughput *= volume_segment.accum_transmittance; | throughput *= volume_segment.accum_transmittance; | ||||
| /* free cached steps */ | /* free cached steps */ | ||||
| kernel_volume_decoupled_free(kg, &volume_segment); | kernel_volume_decoupled_free(kg, &volume_segment); | ||||
| #else | #else | ||||
| /* GPU: no decoupled ray marching, scatter probalistically */ | /* GPU: no decoupled ray marching, scatter probalistically */ | ||||
| int num_samples = kernel_data.integrator.volume_samples; | int num_samples = kernel_data.integrator.volume_samples; | ||||
| float num_samples_inv = 1.0f/num_samples; | float num_samples_inv = 1.0f/num_samples; | ||||
| /* todo: we should cache the shader evaluations from stepping | /* todo: we should cache the shader evaluations from stepping | ||||
| * through the volume, for now we redo them multiple times */ | * through the volume, for now we redo them multiple times */ | ||||
| for(int j = 0; j < num_samples; j++) { | for(int j = 0; j < num_samples; j++) { | ||||
| PathState ps = state; | PathState ps = state; | ||||
| Ray pray = ray; | Ray pray = ray; | ||||
| float3 tp = throughput * num_samples_inv; | float3 tp = throughput * num_samples_inv; | ||||
| /* branch RNG state */ | /* branch RNG state */ | ||||
| path_state_branch(&ps, j, num_samples); | path_state_branch(&ps, j, num_samples); | ||||
| VolumeIntegrateResult result = kernel_volume_integrate( | VolumeIntegrateResult result = kernel_volume_integrate( | ||||
| kg, &ps, &sd, &volume_ray, &L, &tp, rng, heterogeneous); | kg, &ps, &sd, &volume_ray, L, &tp, rng, heterogeneous); | ||||
| #ifdef __VOLUME_SCATTER__ | #ifdef __VOLUME_SCATTER__ | ||||
| if(result == VOLUME_PATH_SCATTERED) { | if(result == VOLUME_PATH_SCATTERED) { | ||||
| /* todo: support equiangular, MIS and all light sampling. | /* todo: support equiangular, MIS and all light sampling. | ||||
| * alternatively get decoupled ray marching working on the GPU */ | * alternatively get decoupled ray marching working on the GPU */ | ||||
| kernel_path_volume_connect_light(kg, rng, &sd, &emission_sd, tp, &state, &L); | kernel_path_volume_connect_light(kg, rng, &sd, &emission_sd, tp, &state, L); | ||||
| if(kernel_path_volume_bounce(kg, | if(kernel_path_volume_bounce(kg, | ||||
| rng, | rng, | ||||
| &sd, | &sd, | ||||
| &tp, | &tp, | ||||
| &ps, | &ps, | ||||
| &L, | L, | ||||
| &pray)) | &pray)) | ||||
| { | { | ||||
| kernel_path_indirect(kg, | kernel_path_indirect(kg, | ||||
| &indirect_sd, | &indirect_sd, | ||||
| &emission_sd, | &emission_sd, | ||||
| rng, | rng, | ||||
| &pray, | &pray, | ||||
| tp, | tp, | ||||
| num_samples, | num_samples, | ||||
| &ps, | &ps, | ||||
| &L); | L); | ||||
| /* for render passes, sum and reset indirect light pass variables | /* for render passes, sum and reset indirect light pass variables | ||||
| * for the next samples */ | * for the next samples */ | ||||
| path_radiance_sum_indirect(&L); | path_radiance_sum_indirect(L); | ||||
| path_radiance_reset_indirect(&L); | path_radiance_reset_indirect(L); | ||||
| } | } | ||||
| } | } | ||||
| #endif /* __VOLUME_SCATTER__ */ | #endif /* __VOLUME_SCATTER__ */ | ||||
| } | } | ||||
| /* todo: avoid this calculation using decoupled ray marching */ | /* todo: avoid this calculation using decoupled ray marching */ | ||||
| kernel_volume_shadow(kg, &emission_sd, &state, &volume_ray, &throughput); | kernel_volume_shadow(kg, &emission_sd, &state, &volume_ray, &throughput); | ||||
| #endif /* __VOLUME_DECOUPLED__ */ | #endif /* __VOLUME_DECOUPLED__ */ | ||||
| Show All 9 Lines | #ifdef __PASSES__ | ||||
| if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) | if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) | ||||
| #endif /* __PASSES__ */ | #endif /* __PASSES__ */ | ||||
| break; | break; | ||||
| } | } | ||||
| #ifdef __BACKGROUND__ | #ifdef __BACKGROUND__ | ||||
| /* sample background shader */ | /* sample background shader */ | ||||
| float3 L_background = indirect_background(kg, &emission_sd, &state, &ray); | float3 L_background = indirect_background(kg, &emission_sd, &state, &ray); | ||||
| path_radiance_accum_background(&L, &state, throughput, L_background); | path_radiance_accum_background(L, &state, throughput, L_background); | ||||
| #endif /* __BACKGROUND__ */ | #endif /* __BACKGROUND__ */ | ||||
| break; | break; | ||||
| } | } | ||||
| /* setup shading */ | /* setup shading */ | ||||
| shader_setup_from_ray(kg, &sd, &isect, &ray); | shader_setup_from_ray(kg, &sd, &isect, &ray); | ||||
| shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN); | shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN); | ||||
| shader_merge_closures(&sd); | shader_merge_closures(&sd); | ||||
| #ifdef __SHADOW_TRICKS__ | #ifdef __SHADOW_TRICKS__ | ||||
| if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { | if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { | ||||
| if(state.flag & PATH_RAY_CAMERA) { | if(state.flag & PATH_RAY_CAMERA) { | ||||
| state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY); | state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY); | ||||
| state.catcher_object = sd.object; | state.catcher_object = sd.object; | ||||
| if(!kernel_data.background.transparent) { | if(!kernel_data.background.transparent) { | ||||
| L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray); | L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; | state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; | ||||
| } | } | ||||
| #endif /* __SHADOW_TRICKS__ */ | #endif /* __SHADOW_TRICKS__ */ | ||||
| Show All 13 Lines | if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) { | ||||
| } | } | ||||
| if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) { | if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| #endif /* __HOLDOUT__ */ | #endif /* __HOLDOUT__ */ | ||||
| /* holdout mask objects do not write data passes */ | /* holdout mask objects do not write data passes */ | ||||
| kernel_write_data_passes(kg, buffer, &L, &sd, sample, &state, throughput); | kernel_write_data_passes(kg, buffer, L, &sd, sample, &state, throughput); | ||||
| #ifdef __EMISSION__ | #ifdef __EMISSION__ | ||||
| /* emission */ | /* emission */ | ||||
| if(sd.flag & SD_EMISSION) { | if(sd.flag & SD_EMISSION) { | ||||
| float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf); | float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf); | ||||
| path_radiance_accum_emission(&L, throughput, emission, state.bounce); | path_radiance_accum_emission(L, throughput, emission, state.bounce); | ||||
| } | } | ||||
| #endif /* __EMISSION__ */ | #endif /* __EMISSION__ */ | ||||
| /* transparency termination */ | /* transparency termination */ | ||||
| if(state.flag & PATH_RAY_TRANSPARENT) { | if(state.flag & PATH_RAY_TRANSPARENT) { | ||||
| /* path termination. this is a strange place to put the termination, it's | /* 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 | * 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 */ | * shader evaluations, only need emission if we are going to terminate */ | ||||
| Show All 10 Lines | if(state.flag & PATH_RAY_TRANSPARENT) { | ||||
| throughput /= probability; | throughput /= probability; | ||||
| } | } | ||||
| } | } | ||||
| #ifdef __AO__ | #ifdef __AO__ | ||||
| /* ambient occlusion */ | /* ambient occlusion */ | ||||
| if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { | if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { | ||||
| kernel_branched_path_ao(kg, &sd, &emission_sd, &L, &state, rng, throughput); | kernel_branched_path_ao(kg, &sd, &emission_sd, L, &state, rng, throughput); | ||||
| } | } | ||||
| #endif /* __AO__ */ | #endif /* __AO__ */ | ||||
| #ifdef __SUBSURFACE__ | #ifdef __SUBSURFACE__ | ||||
| /* bssrdf scatter to a different location on the same object */ | /* bssrdf scatter to a different location on the same object */ | ||||
| if(sd.flag & SD_BSSRDF) { | if(sd.flag & SD_BSSRDF) { | ||||
| kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, &emission_sd, | kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, &emission_sd, | ||||
| &L, &state, rng, &ray, throughput); | L, &state, rng, &ray, throughput); | ||||
| } | } | ||||
| #endif /* __SUBSURFACE__ */ | #endif /* __SUBSURFACE__ */ | ||||
| if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { | if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { | ||||
| PathState hit_state = state; | PathState hit_state = state; | ||||
| #ifdef __EMISSION__ | #ifdef __EMISSION__ | ||||
| /* direct light */ | /* direct light */ | ||||
| if(kernel_data.integrator.use_direct_light) { | if(kernel_data.integrator.use_direct_light) { | ||||
| int all = (kernel_data.integrator.sample_all_lights_direct) || | int all = (kernel_data.integrator.sample_all_lights_direct) || | ||||
| (state.flag & PATH_RAY_SHADOW_CATCHER); | (state.flag & PATH_RAY_SHADOW_CATCHER); | ||||
| kernel_branched_path_surface_connect_light(kg, rng, | kernel_branched_path_surface_connect_light(kg, rng, | ||||
| &sd, &emission_sd, &hit_state, throughput, 1.0f, &L, all); | &sd, &emission_sd, &hit_state, throughput, 1.0f, L, all); | ||||
| } | } | ||||
| #endif /* __EMISSION__ */ | #endif /* __EMISSION__ */ | ||||
| kernel_update_denoising_features(kg, &sd, &state, L); | |||||
| /* indirect light */ | /* indirect light */ | ||||
| kernel_branched_path_surface_indirect_light(kg, rng, | kernel_branched_path_surface_indirect_light(kg, rng, | ||||
| &sd, &indirect_sd, &emission_sd, throughput, 1.0f, &hit_state, &L); | &sd, &indirect_sd, &emission_sd, throughput, 1.0f, &hit_state, L); | ||||
| /* continue in case of transparency */ | /* continue in case of transparency */ | ||||
| throughput *= shader_bsdf_transparency(kg, &sd); | throughput *= shader_bsdf_transparency(kg, &sd); | ||||
| if(is_zero(throughput)) | if(is_zero(throughput)) | ||||
| break; | break; | ||||
| } | } | ||||
| Show All 12 Lines | |||||
| #endif /* __RAY_DIFFERENTIALS__ */ | #endif /* __RAY_DIFFERENTIALS__ */ | ||||
| #ifdef __VOLUME__ | #ifdef __VOLUME__ | ||||
| /* enter/exit volume */ | /* enter/exit volume */ | ||||
| kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); | kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); | ||||
| #endif /* __VOLUME__ */ | #endif /* __VOLUME__ */ | ||||
| } | } | ||||
| float3 L_sum; | |||||
| #ifdef __SHADOW_TRICKS__ | #ifdef __SHADOW_TRICKS__ | ||||
| if(state.flag & PATH_RAY_SHADOW_CATCHER) { | *is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER); | ||||
| L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent); | |||||
| } | |||||
| else | |||||
| #endif /* __SHADOW_TRICKS__ */ | #endif /* __SHADOW_TRICKS__ */ | ||||
| { | |||||
| L_sum = path_radiance_clamp_and_sum(kg, &L); | |||||
| } | |||||
| kernel_write_light_passes(kg, buffer, &L, sample); | |||||
| #ifdef __KERNEL_DEBUG__ | #ifdef __KERNEL_DEBUG__ | ||||
| kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample); | kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample); | ||||
| #endif /* __KERNEL_DEBUG__ */ | #endif /* __KERNEL_DEBUG__ */ | ||||
| return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent); | return 1.0f - L_transparent; | ||||
| } | } | ||||
| ccl_device void kernel_branched_path_trace(KernelGlobals *kg, | ccl_device void kernel_branched_path_trace(KernelGlobals *kg, | ||||
| ccl_global float *buffer, ccl_global uint *rng_state, | ccl_global float *buffer, ccl_global uint *rng_state, | ||||
| int sample, int x, int y, int offset, int stride) | int sample, int x, int y, int offset, int stride) | ||||
| { | { | ||||
| /* buffer offset */ | /* buffer offset */ | ||||
| int index = offset + x + y*stride; | int index = offset + x + y*stride; | ||||
| int pass_stride = kernel_data.film.pass_stride; | int pass_stride = kernel_data.film.pass_stride; | ||||
| rng_state += index; | rng_state += index; | ||||
| buffer += index*pass_stride; | buffer += index*pass_stride; | ||||
| /* initialize random numbers and ray */ | /* initialize random numbers and ray */ | ||||
| RNG rng; | RNG rng; | ||||
| Ray ray; | Ray ray; | ||||
| kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray); | kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray); | ||||
| /* integrate */ | /* integrate */ | ||||
| float4 L; | PathRadiance L; | ||||
| bool is_shadow_catcher; | |||||
| if(ray.t != 0.0f) | |||||
| L = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer); | |||||
| else | |||||
| L = make_float4(0.0f, 0.0f, 0.0f, 0.0f); | |||||
| /* accumulate result in output buffer */ | if(ray.t != 0.0f) { | ||||
| kernel_write_pass_float4(buffer, sample, L); | float alpha = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer, &L, &is_shadow_catcher); | ||||
| kernel_write_result(kg, buffer, sample, &L, alpha, is_shadow_catcher); | |||||
| } | |||||
| else { | |||||
| kernel_write_result(kg, buffer, sample, NULL, 0.0f, false); | |||||
| } | |||||
| path_rng_end(kg, rng_state, rng); | path_rng_end(kg, rng_state, rng); | ||||
| } | } | ||||
| #endif /* __BRANCHED_PATH__ */ | #endif /* __BRANCHED_PATH__ */ | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||
Can we only run this when denoising is enabled?