Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/integrator/integrator_subsurface_random_walk.h
| Show First 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | ccl_device_forceinline float3 subsurface_random_walk_pdf(float3 sigma_t, | ||||
| } | } | ||||
| return hit ? T : sigma_t * T; | return hit ? T : sigma_t * T; | ||||
| } | } | ||||
| /* Define the below variable to get the similarity code active, | /* Define the below variable to get the similarity code active, | ||||
| * and the value represents the cutoff level */ | * and the value represents the cutoff level */ | ||||
| #define SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL 9 | #define SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL 9 | ||||
| ccl_device_inline bool subsurface_random_walk(INTEGRATOR_STATE_ARGS, | ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| RNGState rng_state, | RNGState rng_state, | ||||
| ccl_private Ray &ray, | ccl_private Ray &ray, | ||||
| ccl_private LocalIntersection &ss_isect) | ccl_private LocalIntersection &ss_isect) | ||||
| { | { | ||||
| 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); | ||||
| const float3 P = INTEGRATOR_STATE(ray, P); | const float3 P = INTEGRATOR_STATE(state, ray, P); | ||||
| const float3 N = INTEGRATOR_STATE(ray, D); | const float3 N = INTEGRATOR_STATE(state, ray, D); | ||||
| const float ray_dP = INTEGRATOR_STATE(ray, dP); | const float ray_dP = INTEGRATOR_STATE(state, ray, dP); | ||||
| const float time = INTEGRATOR_STATE(ray, time); | const float time = INTEGRATOR_STATE(state, ray, time); | ||||
| const float3 Ng = INTEGRATOR_STATE(isect, Ng); | const float3 Ng = INTEGRATOR_STATE(state, isect, Ng); | ||||
| const int object = INTEGRATOR_STATE(isect, object); | const int object = INTEGRATOR_STATE(state, isect, object); | ||||
| /* Sample diffuse surface scatter into the object. */ | /* Sample diffuse surface scatter into the object. */ | ||||
| float3 D; | float3 D; | ||||
| float pdf; | float pdf; | ||||
| sample_cos_hemisphere(-N, bssrdf_u, bssrdf_v, &D, &pdf); | sample_cos_hemisphere(-N, bssrdf_u, bssrdf_v, &D, &pdf); | ||||
| if (dot(-Ng, D) <= 0.0f) { | if (dot(-Ng, D) <= 0.0f) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| Show All 9 Lines | |||||
| #ifndef __KERNEL_OPTIX__ | #ifndef __KERNEL_OPTIX__ | ||||
| /* Compute or fetch object transforms. */ | /* Compute or fetch object transforms. */ | ||||
| Transform ob_itfm ccl_optional_struct_init; | Transform ob_itfm ccl_optional_struct_init; | ||||
| Transform ob_tfm = object_fetch_transform_motion_test(kg, object, time, &ob_itfm); | Transform ob_tfm = object_fetch_transform_motion_test(kg, object, time, &ob_itfm); | ||||
| #endif | #endif | ||||
| /* Convert subsurface to volume coefficients. | /* Convert subsurface to volume coefficients. | ||||
| * The single-scattering albedo is named alpha to avoid confusion with the surface albedo. */ | * The single-scattering albedo is named alpha to avoid confusion with the surface albedo. */ | ||||
| const float3 albedo = INTEGRATOR_STATE(subsurface, albedo); | const float3 albedo = INTEGRATOR_STATE(state, subsurface, albedo); | ||||
| const float3 radius = INTEGRATOR_STATE(subsurface, radius); | const float3 radius = INTEGRATOR_STATE(state, subsurface, radius); | ||||
| const float anisotropy = INTEGRATOR_STATE(subsurface, anisotropy); | const float anisotropy = INTEGRATOR_STATE(state, subsurface, anisotropy); | ||||
| float3 sigma_t, alpha; | float3 sigma_t, alpha; | ||||
| float3 throughput = INTEGRATOR_STATE_WRITE(path, throughput); | float3 throughput = INTEGRATOR_STATE_WRITE(state, path, throughput); | ||||
| subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput); | subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput); | ||||
| float3 sigma_s = sigma_t * alpha; | float3 sigma_s = sigma_t * alpha; | ||||
| /* Theoretically it should be better to use the exact alpha for the channel we're sampling at | /* Theoretically it should be better to use the exact alpha for the channel we're sampling at | ||||
| * each bounce, but in practice there doesn't seem to be a noticeable difference in exchange | * each bounce, but in practice there doesn't seem to be a noticeable difference in exchange | ||||
| * for making the code significantly more complex and slower (if direction sampling depends on | * for making the code significantly more complex and slower (if direction sampling depends on | ||||
| * the sampled channel, we need to compute its PDF per-channel and consider it for MIS later on). | * the sampled channel, we need to compute its PDF per-channel and consider it for MIS later on). | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | else if (throughput.x < VOLUME_THROUGHPUT_EPSILON && | ||||
| throughput.z < VOLUME_THROUGHPUT_EPSILON) { | throughput.z < VOLUME_THROUGHPUT_EPSILON) { | ||||
| /* Avoid unnecessary work and precision issue when throughput gets really small. */ | /* Avoid unnecessary work and precision issue when throughput gets really small. */ | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (hit) { | if (hit) { | ||||
| kernel_assert(isfinite3_safe(throughput)); | kernel_assert(isfinite3_safe(throughput)); | ||||
| INTEGRATOR_STATE_WRITE(path, throughput) = throughput; | INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput; | ||||
| } | } | ||||
| return hit; | return hit; | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||