Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernel_path.h
| Show First 20 Lines • Show All 353 Lines • ▼ Show 20 Lines | #endif | ||||
| if(!shadow_blocked(kg, state, &light_ray, &ao_shadow)) | if(!shadow_blocked(kg, 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, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #ifdef __SUBSURFACE__ | #ifdef __SUBSURFACE__ | ||||
| # ifdef __VOLUME__ | |||||
| ccl_device void kernel_path_subsurface_update_volume_stack(KernelGlobals *kg, | |||||
| Ray *ray, | |||||
| VolumeStack *stack) | |||||
| { | |||||
| kernel_assert(kernel_data.integrator.use_volumes); | |||||
| Ray volume_ray = *ray; | |||||
| Intersection isect; | |||||
| const float3 Pend = volume_ray.P + volume_ray.D*volume_ray.t; | |||||
| while( | |||||
| scene_intersect(kg, &volume_ray, PATH_RAY_ALL_VISIBILITY, | |||||
| &isect, NULL, 0.0f, 0.0f)) { | |||||
| ShaderData sd; | |||||
| shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); | |||||
| kernel_volume_stack_enter_exit(kg, &sd, stack); | |||||
| /* Move ray forward. */ | |||||
| volume_ray.P = ray_offset(sd.P, -sd.Ng); | |||||
| volume_ray.D = normalize_len(Pend - volume_ray.P, | |||||
| &volume_ray.t); | |||||
| /* TODO(sergey): Find a faster way detecting that ray_offset moved | |||||
| * us pass through the end point. | |||||
| */ | |||||
| if(dot(ray->D, volume_ray.D) < 0.0f) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| # endif | |||||
| ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput) | ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput) | ||||
| { | { | ||||
| float bssrdf_probability; | float bssrdf_probability; | ||||
| ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability); | ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability); | ||||
| /* modify throughput for picking bssrdf or bsdf */ | /* modify throughput for picking bssrdf or bsdf */ | ||||
| *throughput *= bssrdf_probability; | *throughput *= bssrdf_probability; | ||||
| /* do bssrdf scatter step if we picked a bssrdf closure */ | /* do bssrdf scatter step if we picked a bssrdf closure */ | ||||
| if(sc) { | if(sc) { | ||||
| uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb); | uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb); | ||||
| ShaderData bssrdf_sd[BSSRDF_MAX_HITS]; | ShaderData bssrdf_sd[BSSRDF_MAX_HITS]; | ||||
| float bssrdf_u, bssrdf_v; | float bssrdf_u, bssrdf_v; | ||||
| path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); | path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); | ||||
| int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false); | int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false); | ||||
| #ifdef __VOLUME__ | |||||
| Ray volume_ray = *ray; | |||||
| #endif | |||||
| /* compute lighting with the BSDF closure */ | /* compute lighting with the BSDF closure */ | ||||
| for(int hit = 0; hit < num_hits; hit++) { | for(int hit = 0; hit < num_hits; hit++) { | ||||
| float3 tp = *throughput; | float3 tp = *throughput; | ||||
| PathState hit_state = *state; | PathState hit_state = *state; | ||||
| Ray hit_ray = *ray; | Ray hit_ray = *ray; | ||||
| hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR; | hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR; | ||||
| hit_state.rng_offset += PRNG_BOUNCE_NUM; | hit_state.rng_offset += PRNG_BOUNCE_NUM; | ||||
| kernel_path_surface_connect_light(kg, rng, &bssrdf_sd[hit], tp, state, L); | kernel_path_surface_connect_light(kg, rng, &bssrdf_sd[hit], tp, state, L); | ||||
| if(kernel_path_surface_bounce(kg, rng, &bssrdf_sd[hit], &tp, &hit_state, L, &hit_ray)) { | if(kernel_path_surface_bounce(kg, rng, &bssrdf_sd[hit], &tp, &hit_state, L, &hit_ray)) { | ||||
| #ifdef __LAMP_MIS__ | #ifdef __LAMP_MIS__ | ||||
| hit_state.ray_t = 0.0f; | hit_state.ray_t = 0.0f; | ||||
| #endif | #endif | ||||
| #ifdef __VOLUME__ | |||||
| if(kernel_data.integrator.use_volumes) { | |||||
| /* Setup ray from previous surface point to the new one. */ | |||||
| volume_ray.D = normalize_len(hit_ray.P - volume_ray.P, | |||||
| &volume_ray.t); | |||||
| kernel_path_subsurface_update_volume_stack( | |||||
| kg, | |||||
| &volume_ray, | |||||
| hit_state.volume_stack); | |||||
| /* Move volume ray forward. */ | |||||
| volume_ray.P = hit_ray.P; | |||||
| } | |||||
| #endif | |||||
| kernel_path_indirect(kg, rng, hit_ray, tp, state->num_samples, hit_state, L); | kernel_path_indirect(kg, rng, hit_ray, tp, state->num_samples, hit_state, 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); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | for(int j = 0; j < num_samples; j++) { | ||||
| * 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); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #ifdef __SUBSURFACE__ | #ifdef __SUBSURFACE__ | ||||
| ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, float3 throughput) | ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, | ||||
| ShaderData *sd, | |||||
| PathRadiance *L, | |||||
| PathState *state, | |||||
| RNG *rng, | |||||
| Ray *ray, | |||||
| float3 throughput) | |||||
| { | { | ||||
| for(int i = 0; i< sd->num_closure; i++) { | for(int i = 0; i< sd->num_closure; i++) { | ||||
| ShaderClosure *sc = &sd->closure[i]; | ShaderClosure *sc = &sd->closure[i]; | ||||
| if(!CLOSURE_IS_BSSRDF(sc->type)) | if(!CLOSURE_IS_BSSRDF(sc->type)) | ||||
| continue; | continue; | ||||
| /* set up random number generator */ | /* set up random number generator */ | ||||
| uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb); | uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb); | ||||
| int num_samples = kernel_data.integrator.subsurface_samples; | int num_samples = kernel_data.integrator.subsurface_samples; | ||||
| float num_samples_inv = 1.0f/num_samples; | float num_samples_inv = 1.0f/num_samples; | ||||
| RNG bssrdf_rng = cmj_hash(*rng, i); | RNG bssrdf_rng = cmj_hash(*rng, i); | ||||
| state->flag |= PATH_RAY_BSSRDF_ANCESTOR; | state->flag |= PATH_RAY_BSSRDF_ANCESTOR; | ||||
| /* do subsurface scatter step with copy of shader data, this will | /* do subsurface scatter step with copy of shader data, this will | ||||
| * replace the BSSRDF with a diffuse BSDF closure */ | * replace the BSSRDF with a diffuse BSDF closure */ | ||||
| for(int j = 0; j < num_samples; j++) { | for(int j = 0; j < num_samples; j++) { | ||||
| ShaderData bssrdf_sd[BSSRDF_MAX_HITS]; | ShaderData bssrdf_sd[BSSRDF_MAX_HITS]; | ||||
| float bssrdf_u, bssrdf_v; | float bssrdf_u, bssrdf_v; | ||||
| path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); | path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); | ||||
| int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true); | int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true); | ||||
| # ifdef __VOLUME__ | |||||
| Ray volume_ray = *ray; | |||||
| # endif | |||||
| /* compute lighting with the BSDF closure */ | /* compute lighting with the BSDF closure */ | ||||
| for(int hit = 0; hit < num_hits; hit++) { | for(int hit = 0; hit < num_hits; hit++) { | ||||
| PathState hit_state = *state; | PathState hit_state = *state; | ||||
| path_state_branch(&hit_state, j, num_samples); | path_state_branch(&hit_state, j, num_samples); | ||||
| #ifdef __VOLUME__ | |||||
| if(kernel_data.integrator.use_volumes) { | |||||
| /* Setup ray from previous surface point to the new one. */ | |||||
| float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng); | |||||
| volume_ray.D = normalize_len(P - volume_ray.P, | |||||
| &volume_ray.t); | |||||
| kernel_path_subsurface_update_volume_stack( | |||||
| kg, | |||||
| &volume_ray, | |||||
| hit_state.volume_stack); | |||||
| /* Move volume ray forward. */ | |||||
| volume_ray.P = P; | |||||
| } | |||||
| #endif | |||||
| #if defined(__EMISSION__) && defined(__BRANCHED_PATH__) | #if defined(__EMISSION__) && defined(__BRANCHED_PATH__) | ||||
| /* direct light */ | /* direct light */ | ||||
| if(kernel_data.integrator.use_direct_light) { | if(kernel_data.integrator.use_direct_light) { | ||||
| bool all = kernel_data.integrator.sample_all_lights_direct; | bool all = kernel_data.integrator.sample_all_lights_direct; | ||||
| kernel_branched_path_surface_connect_light(kg, rng, | kernel_branched_path_surface_connect_light(kg, rng, | ||||
| &bssrdf_sd[hit], &hit_state, throughput, num_samples_inv, L, all); | &bssrdf_sd[hit], &hit_state, throughput, num_samples_inv, L, all); | ||||
| } | } | ||||
| #endif | #endif | ||||
| ▲ Show 20 Lines • Show All 248 Lines • ▼ Show 20 Lines | #ifdef __AO__ | ||||
| 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, &L, &state, rng, throughput); | kernel_branched_path_ao(kg, &sd, &L, &state, rng, throughput); | ||||
| } | } | ||||
| #endif | #endif | ||||
| #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, &L, &state, rng, throughput); | kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state, | ||||
| rng, &ray, throughput); | |||||
| } | } | ||||
| #endif | #endif | ||||
| 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 */ | ||||
| ▲ Show 20 Lines • Show All 136 Lines • Show Last 20 Lines | |||||