diff options
Diffstat (limited to 'intern/cycles/kernel/kernel_path.h')
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 1210 |
1 files changed, 565 insertions, 645 deletions
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index a1fc6028293..2be1b745632 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -50,309 +50,298 @@ CCL_NAMESPACE_BEGIN -ccl_device_forceinline bool kernel_path_scene_intersect( - KernelGlobals *kg, - ccl_addr_space PathState *state, - Ray *ray, - Intersection *isect, - PathRadiance *L) +ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg, + ccl_addr_space PathState *state, + Ray *ray, + Intersection *isect, + PathRadiance *L) { - PROFILING_INIT(kg, PROFILING_SCENE_INTERSECT); + PROFILING_INIT(kg, PROFILING_SCENE_INTERSECT); - uint visibility = path_state_ray_visibility(kg, state); + uint visibility = path_state_ray_visibility(kg, state); - if(path_state_ao_bounce(kg, state)) { - visibility = PATH_RAY_SHADOW; - ray->t = kernel_data.background.ao_distance; - } + if (path_state_ao_bounce(kg, state)) { + visibility = PATH_RAY_SHADOW; + ray->t = kernel_data.background.ao_distance; + } #ifdef __HAIR__ - float difl = 0.0f, extmax = 0.0f; - uint lcg_state = 0; + 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; - } + 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); - } + extmax = kernel_data.curve.maximum_width; + lcg_state = lcg_state_init_addrspace(state, 0x51633e2d); + } - bool hit = scene_intersect(kg, *ray, visibility, isect, &lcg_state, difl, extmax); + 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__ */ + 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; + 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) +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) { - PROFILING_INIT(kg, PROFILING_INDIRECT_EMISSION); + PROFILING_INIT(kg, PROFILING_INDIRECT_EMISSION); #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__ */ + 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 *sd, - PathRadiance *L) +ccl_device_forceinline void kernel_path_background(KernelGlobals *kg, + ccl_addr_space PathState *state, + ccl_addr_space Ray *ray, + float3 throughput, + ShaderData *sd, + PathRadiance *L) { - /* eval background shader if nothing hit */ - if(kernel_data.background.transparent && (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { - L->transparent += average(throughput); + /* eval background shader if nothing hit */ + if (kernel_data.background.transparent && (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { + L->transparent += average(throughput); #ifdef __PASSES__ - if(!(kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND))) -#endif /* __PASSES__ */ - return; - } + if (!(kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND))) +#endif /* __PASSES__ */ + return; + } - /* When using the ao bounces approximation, adjust background - * shader intensity with ao factor. */ - if(path_state_ao_bounce(kg, state)) { - throughput *= kernel_data.background.ao_bounces_factor; - } + /* When using the ao bounces approximation, adjust background + * shader intensity with ao factor. */ + if (path_state_ao_bounce(kg, state)) { + throughput *= kernel_data.background.ao_bounces_factor; + } #ifdef __BACKGROUND__ - /* sample background shader */ - float3 L_background = indirect_background(kg, sd, state, ray); - path_radiance_accum_background(L, state, throughput, L_background); -#endif /* __BACKGROUND__ */ + /* sample background shader */ + float3 L_background = indirect_background(kg, sd, state, ray); + path_radiance_accum_background(L, state, throughput, L_background); +#endif /* __BACKGROUND__ */ } #ifndef __SPLIT_KERNEL__ -#ifdef __VOLUME__ -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__ +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) { - PROFILING_INIT(kg, PROFILING_VOLUME); - - /* Sanitize volume stack. */ - if(!hit) { - kernel_volume_clean_stack(kg, state->volume_stack); - } - - if(state->volume_stack[0].shader == SHADER_NONE) { - return VOLUME_PATH_ATTENUATED; - } - - /* volume attenuation, emission, scatter */ - 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(kg, state, PRNG_PHASE_CHANNEL); - float rscatter = path_state_rng_1D(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->state, 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->state, ray)) - return VOLUME_PATH_SCATTERED; - else - return VOLUME_PATH_MISSED; - } -# endif /* __VOLUME_SCATTER__ */ - } - - return VOLUME_PATH_ATTENUATED; + PROFILING_INIT(kg, PROFILING_VOLUME); + + /* Sanitize volume stack. */ + if (!hit) { + kernel_volume_clean_stack(kg, state->volume_stack); + } + + if (state->volume_stack[0].shader == SHADER_NONE) { + return VOLUME_PATH_ATTENUATED; + } + + /* volume attenuation, emission, scatter */ + 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(kg, state, PRNG_PHASE_CHANNEL); + float rscatter = path_state_rng_1D(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->state, 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->state, ray)) + return VOLUME_PATH_SCATTERED; + else + return VOLUME_PATH_MISSED; + } +# endif /* __VOLUME_SCATTER__ */ + } + + return VOLUME_PATH_ATTENUATED; } -#endif /* __VOLUME__ */ - -#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) +# endif /* __VOLUME__ */ + +#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) { - PROFILING_INIT(kg, PROFILING_SHADER_APPLY); + PROFILING_INIT(kg, PROFILING_SHADER_APPLY); #ifdef __SHADOW_TRICKS__ - if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { - if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) { - 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 */ + if ((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) { + 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_TRANSPARENT_BACKGROUND)) - { - 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); - } - } + if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) && + (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { + 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; + /* 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, @@ -363,44 +352,44 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg, float3 throughput, float3 ao_alpha) { - PROFILING_INIT(kg, PROFILING_AO); - - /* todo: solve correlation */ - float bsdf_u, bsdf_v; - - path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); - - float ao_factor = kernel_data.background.ao_factor; - float3 ao_N; - float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N); - float3 ao_D; - float ao_pdf; - - sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); - - if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { - Ray light_ray; - float3 ao_shadow; - - light_ray.P = ray_offset(sd->P, sd->Ng); - light_ray.D = ao_D; - light_ray.t = kernel_data.background.ao_distance; - light_ray.time = sd->time; - light_ray.dP = sd->dP; - light_ray.dD = differential3_zero(); - - if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) { - path_radiance_accum_ao(L, state, throughput, ao_alpha, ao_bsdf, ao_shadow); - } - else { - path_radiance_accum_total_ao(L, state, throughput, ao_bsdf); - } - } + PROFILING_INIT(kg, PROFILING_AO); + + /* todo: solve correlation */ + float bsdf_u, bsdf_v; + + path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); + + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N); + float3 ao_D; + float ao_pdf; + + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + + if (dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { + Ray light_ray; + float3 ao_shadow; + + light_ray.P = ray_offset(sd->P, sd->Ng); + light_ray.D = ao_D; + light_ray.t = kernel_data.background.ao_distance; + light_ray.time = sd->time; + light_ray.dP = sd->dP; + light_ray.dD = differential3_zero(); + + if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) { + path_radiance_accum_ao(L, state, throughput, ao_alpha, ao_bsdf, ao_shadow); + } + else { + path_radiance_accum_total_ao(L, state, throughput, ao_bsdf); + } + } } #ifndef __SPLIT_KERNEL__ -#if defined(__BRANCHED_PATH__) || defined(__BAKING__) +# if defined(__BRANCHED_PATH__) || defined(__BAKING__) ccl_device void kernel_path_indirect(KernelGlobals *kg, ShaderData *sd, @@ -410,369 +399,300 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, PathState *state, PathRadiance *L) { -#ifdef __SUBSURFACE__ - SubsurfaceIndirectRays ss_indirect; - kernel_path_subsurface_init_indirect(&ss_indirect); - - for(;;) { -#endif /* __SUBSURFACE__ */ - - /* path iteration */ - for(;;) { - /* Find intersection with objects in scene. */ - Intersection isect; - 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, sd, L); - -#ifdef __VOLUME__ - /* 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) { - kernel_path_background(kg, state, ray, throughput, sd, L); - break; - } - else if(path_state_ao_bounce(kg, state)) { - break; - } - - /* Setup shader data. */ - shader_setup_from_ray(kg, sd, &isect, ray); - - /* Skip most work for volume bounding surface. */ -#ifdef __VOLUME__ - if(!(sd->flag & SD_HAS_ONLY_VOLUME)) { -#endif - - /* Evaluate shader. */ - shader_eval_surface(kg, sd, state, state->flag); - shader_prepare_closures(sd, state); - - /* Apply shadow catcher, holdout, emission. */ - if(!kernel_path_shader_apply(kg, - sd, - state, - ray, - throughput, - emission_sd, - L, - NULL)) - { - break; - } - - /* 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); - - if(probability == 0.0f) { - break; - } - else if(probability != 1.0f) { - float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE); - - if(terminate >= probability) - break; - - throughput /= probability; - } - - kernel_update_denoising_features(kg, sd, state, L); - -#ifdef __AO__ - /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { - kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f)); - } -#endif /* __AO__ */ - - -#ifdef __SUBSURFACE__ - /* bssrdf scatter to a different location on the same object, replacing - * the closures with a diffuse BSDF */ - if(sd->flag & SD_BSSRDF) { - if(kernel_path_subsurface_scatter(kg, - sd, - emission_sd, - L, - state, - ray, - &throughput, - &ss_indirect)) - { - break; - } - } -#endif /* __SUBSURFACE__ */ - -#if defined(__EMISSION__) - if(kernel_data.integrator.use_direct_light) { - int all = (kernel_data.integrator.sample_all_lights_indirect) || - (state->flag & PATH_RAY_SHADOW_CATCHER); - kernel_branched_path_surface_connect_light(kg, - sd, - emission_sd, - state, - throughput, - 1.0f, - L, - all); - } -#endif /* defined(__EMISSION__) */ - -#ifdef __VOLUME__ - } -#endif - - if(!kernel_path_surface_bounce(kg, sd, &throughput, state, &L->state, ray)) - break; - } - -#ifdef __SUBSURFACE__ - /* Trace indirect subsurface rays by restarting the loop. this uses less - * stack memory than invoking kernel_path_indirect. - */ - if(ss_indirect.num_rays) { - kernel_path_subsurface_setup_indirect(kg, - &ss_indirect, - state, - ray, - L, - &throughput); - } - else { - break; - } - } -#endif /* __SUBSURFACE__ */ +# ifdef __SUBSURFACE__ + SubsurfaceIndirectRays ss_indirect; + kernel_path_subsurface_init_indirect(&ss_indirect); + + for (;;) { +# endif /* __SUBSURFACE__ */ + + /* path iteration */ + for (;;) { + /* Find intersection with objects in scene. */ + Intersection isect; + 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, sd, L); + +# ifdef __VOLUME__ + /* 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) { + kernel_path_background(kg, state, ray, throughput, sd, L); + break; + } + else if (path_state_ao_bounce(kg, state)) { + break; + } + + /* Setup shader data. */ + shader_setup_from_ray(kg, sd, &isect, ray); + + /* Skip most work for volume bounding surface. */ +# ifdef __VOLUME__ + if (!(sd->flag & SD_HAS_ONLY_VOLUME)) { +# endif + + /* Evaluate shader. */ + shader_eval_surface(kg, sd, state, state->flag); + shader_prepare_closures(sd, state); + + /* Apply shadow catcher, holdout, emission. */ + if (!kernel_path_shader_apply(kg, sd, state, ray, throughput, emission_sd, L, NULL)) { + break; + } + + /* 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); + + if (probability == 0.0f) { + break; + } + else if (probability != 1.0f) { + float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE); + + if (terminate >= probability) + break; + + throughput /= probability; + } + + kernel_update_denoising_features(kg, sd, state, L); + +# ifdef __AO__ + /* ambient occlusion */ + if (kernel_data.integrator.use_ambient_occlusion) { + kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f)); + } +# endif /* __AO__ */ + +# ifdef __SUBSURFACE__ + /* bssrdf scatter to a different location on the same object, replacing + * the closures with a diffuse BSDF */ + if (sd->flag & SD_BSSRDF) { + if (kernel_path_subsurface_scatter( + kg, sd, emission_sd, L, state, ray, &throughput, &ss_indirect)) { + break; + } + } +# endif /* __SUBSURFACE__ */ + +# if defined(__EMISSION__) + if (kernel_data.integrator.use_direct_light) { + int all = (kernel_data.integrator.sample_all_lights_indirect) || + (state->flag & PATH_RAY_SHADOW_CATCHER); + kernel_branched_path_surface_connect_light( + kg, sd, emission_sd, state, throughput, 1.0f, L, all); + } +# endif /* defined(__EMISSION__) */ + +# ifdef __VOLUME__ + } +# endif + + if (!kernel_path_surface_bounce(kg, sd, &throughput, state, &L->state, ray)) + break; + } + +# ifdef __SUBSURFACE__ + /* Trace indirect subsurface rays by restarting the loop. this uses less + * stack memory than invoking kernel_path_indirect. + */ + if (ss_indirect.num_rays) { + kernel_path_subsurface_setup_indirect(kg, &ss_indirect, state, ray, L, &throughput); + } + else { + break; + } + } +# endif /* __SUBSURFACE__ */ } -#endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */ +# endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */ -ccl_device_forceinline void kernel_path_integrate( - KernelGlobals *kg, - PathState *state, - float3 throughput, - Ray *ray, - PathRadiance *L, - ccl_global float *buffer, - ShaderData *emission_sd) +ccl_device_forceinline void kernel_path_integrate(KernelGlobals *kg, + PathState *state, + float3 throughput, + Ray *ray, + PathRadiance *L, + ccl_global float *buffer, + ShaderData *emission_sd) { - PROFILING_INIT(kg, PROFILING_PATH_INTEGRATE); - - /* Shader data memory used for both volumes and surfaces, saves stack space. */ - ShaderData sd; - -#ifdef __SUBSURFACE__ - SubsurfaceIndirectRays ss_indirect; - kernel_path_subsurface_init_indirect(&ss_indirect); - - for(;;) { -#endif /* __SUBSURFACE__ */ - - /* path iteration */ - for(;;) { - /* Find intersection with objects in scene. */ - Intersection isect; - 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, &sd, L); - -#ifdef __VOLUME__ - /* 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) { - kernel_path_background(kg, state, ray, throughput, &sd, L); - break; - } - else if(path_state_ao_bounce(kg, state)) { - break; - } - - /* Setup shader data. */ - shader_setup_from_ray(kg, &sd, &isect, ray); - - /* Skip most work for volume bounding surface. */ -#ifdef __VOLUME__ - if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { -#endif - - /* Evaluate shader. */ - shader_eval_surface(kg, &sd, state, state->flag); - shader_prepare_closures(&sd, state); - - /* Apply shadow catcher, holdout, emission. */ - if(!kernel_path_shader_apply(kg, - &sd, - state, - ray, - throughput, - emission_sd, - L, - buffer)) - { - break; - } - - /* 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); - - if(probability == 0.0f) { - break; - } - else if(probability != 1.0f) { - float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE); - if(terminate >= probability) - break; - - throughput /= probability; - } - - kernel_update_denoising_features(kg, &sd, state, L); - -#ifdef __AO__ - /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { - kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd)); - } -#endif /* __AO__ */ - -#ifdef __SUBSURFACE__ - /* bssrdf scatter to a different location on the same object, replacing - * the closures with a diffuse BSDF */ - if(sd.flag & SD_BSSRDF) { - if(kernel_path_subsurface_scatter(kg, - &sd, - emission_sd, - L, - state, - ray, - &throughput, - &ss_indirect)) - { - break; - } - } -#endif /* __SUBSURFACE__ */ - - /* direct lighting */ - kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L); - -#ifdef __VOLUME__ - } -#endif - - /* compute direct lighting and next bounce */ - if(!kernel_path_surface_bounce(kg, &sd, &throughput, state, &L->state, ray)) - break; - } - -#ifdef __SUBSURFACE__ - /* Trace indirect subsurface rays by restarting the loop. this uses less - * stack memory than invoking kernel_path_indirect. - */ - if(ss_indirect.num_rays) { - kernel_path_subsurface_setup_indirect(kg, - &ss_indirect, - state, - ray, - L, - &throughput); - } - else { - break; - } - } -#endif /* __SUBSURFACE__ */ + PROFILING_INIT(kg, PROFILING_PATH_INTEGRATE); + + /* Shader data memory used for both volumes and surfaces, saves stack space. */ + ShaderData sd; + +# ifdef __SUBSURFACE__ + SubsurfaceIndirectRays ss_indirect; + kernel_path_subsurface_init_indirect(&ss_indirect); + + for (;;) { +# endif /* __SUBSURFACE__ */ + + /* path iteration */ + for (;;) { + /* Find intersection with objects in scene. */ + Intersection isect; + 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, &sd, L); + +# ifdef __VOLUME__ + /* 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) { + kernel_path_background(kg, state, ray, throughput, &sd, L); + break; + } + else if (path_state_ao_bounce(kg, state)) { + break; + } + + /* Setup shader data. */ + shader_setup_from_ray(kg, &sd, &isect, ray); + + /* Skip most work for volume bounding surface. */ +# ifdef __VOLUME__ + if (!(sd.flag & SD_HAS_ONLY_VOLUME)) { +# endif + + /* Evaluate shader. */ + shader_eval_surface(kg, &sd, state, state->flag); + shader_prepare_closures(&sd, state); + + /* Apply shadow catcher, holdout, emission. */ + if (!kernel_path_shader_apply(kg, &sd, state, ray, throughput, emission_sd, L, buffer)) { + break; + } + + /* 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); + + if (probability == 0.0f) { + break; + } + else if (probability != 1.0f) { + float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE); + if (terminate >= probability) + break; + + throughput /= probability; + } + + kernel_update_denoising_features(kg, &sd, state, L); + +# ifdef __AO__ + /* ambient occlusion */ + if (kernel_data.integrator.use_ambient_occlusion) { + kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd)); + } +# endif /* __AO__ */ + +# ifdef __SUBSURFACE__ + /* bssrdf scatter to a different location on the same object, replacing + * the closures with a diffuse BSDF */ + if (sd.flag & SD_BSSRDF) { + if (kernel_path_subsurface_scatter( + kg, &sd, emission_sd, L, state, ray, &throughput, &ss_indirect)) { + break; + } + } +# endif /* __SUBSURFACE__ */ + + /* direct lighting */ + kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L); + +# ifdef __VOLUME__ + } +# endif + + /* compute direct lighting and next bounce */ + if (!kernel_path_surface_bounce(kg, &sd, &throughput, state, &L->state, ray)) + break; + } + +# ifdef __SUBSURFACE__ + /* Trace indirect subsurface rays by restarting the loop. this uses less + * stack memory than invoking kernel_path_indirect. + */ + if (ss_indirect.num_rays) { + kernel_path_subsurface_setup_indirect(kg, &ss_indirect, state, ray, L, &throughput); + } + else { + break; + } + } +# endif /* __SUBSURFACE__ */ } -ccl_device void kernel_path_trace(KernelGlobals *kg, - ccl_global float *buffer, - int sample, int x, int y, int offset, int stride) +ccl_device void kernel_path_trace( + KernelGlobals *kg, ccl_global float *buffer, int sample, int x, int y, int offset, int stride) { - PROFILING_INIT(kg, PROFILING_RAY_SETUP); + PROFILING_INIT(kg, PROFILING_RAY_SETUP); - /* buffer offset */ - int index = offset + x + y*stride; - int pass_stride = kernel_data.film.pass_stride; + /* buffer offset */ + int index = offset + x + y * stride; + int pass_stride = kernel_data.film.pass_stride; - buffer += index*pass_stride; + buffer += index * pass_stride; - /* Initialize random numbers and sample ray. */ - uint rng_hash; - Ray ray; + /* Initialize random numbers and sample ray. */ + uint rng_hash; + Ray ray; - kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray); + kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray); - if(ray.t == 0.0f) { - return; - } + if (ray.t == 0.0f) { + return; + } - /* Initialize state. */ - float3 throughput = make_float3(1.0f, 1.0f, 1.0f); + /* Initialize state. */ + float3 throughput = make_float3(1.0f, 1.0f, 1.0f); - PathRadiance L; - path_radiance_init(&L, kernel_data.film.use_light_pass); + PathRadiance L; + path_radiance_init(&L, kernel_data.film.use_light_pass); - ShaderDataTinyStorage emission_sd_storage; - ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); + ShaderDataTinyStorage emission_sd_storage; + ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - PathState state; - path_state_init(kg, emission_sd, &state, rng_hash, sample, &ray); + 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); + /* Integrate. */ + kernel_path_integrate(kg, &state, throughput, &ray, &L, buffer, emission_sd); - kernel_write_result(kg, buffer, sample, &L); + kernel_write_result(kg, buffer, sample, &L); } -#endif /* __SPLIT_KERNEL__ */ +#endif /* __SPLIT_KERNEL__ */ CCL_NAMESPACE_END |