26ccl_device void subsurface_random_walk_remap(
const float albedo,
33 const float g2 = g * g;
34 const float g3 = g2 * g;
35 const float g4 = g3 * g;
36 const float g5 = g4 * g;
37 const float g6 = g5 * g;
38 const float g7 = g6 * g;
40 const float A = 1.8260523782f + -1.28451056436f * g + -1.79904629312f * g2 +
41 9.19393289202f * g3 + -22.8215585862f * g4 + 32.0234874259f * g5 +
42 -23.6264803333f * g6 + 7.21067002658f * g7;
43 const float B = 4.98511194385f +
45 expf(31.1491581433f * g + -201.847017512f * g2 + 841.576016723f * g3 +
46 -2018.09288505f * g4 + 2731.71560286f * g5 + -1935.41424244f * g6 +
48 const float C = 1.09686102424f + -0.394704063468f * g + 1.05258115941f * g2 +
49 -8.83963712726f * g3 + 28.8643230661f * g4 + -46.8802913581f * g5 +
50 38.5402837518f * g6 + -12.7181042538f * g7;
51 const float D = 0.496310210422f + 0.360146581622f * g + -2.15139309747f * g2 +
52 17.8896899217f * g3 + -55.2984010333f * g4 + 82.065982243f * g5 +
53 -58.5106008578f * g6 + 15.8478295021f * g7;
54 const float E = 4.23190299701f +
56 expf(76.7316253952f * g + -594.356773233f * g2 + 2448.8834203f * g3 +
57 -5576.68528998f * g4 + 7116.60171912f * g5 + -4763.54467887f * g6 +
59 const float F = 2.40602999408f + -2.51814844609f * g + 9.18494908356f * g2 +
60 -79.2191708682f * g3 + 259.082868209f * g4 + -403.613804597f * g5 +
61 302.85712436f * g6 + -87.4370473567f * g7;
67 *alpha =
clamp(*alpha, 0.0f, 0.999999f);
69 float sigma_t_prime = 1.0f /
fmaxf(d, 1e-16f);
70 *sigma_t = sigma_t_prime / (1.0f - g);
75 const float anisotropy,
96 const float min_alpha = 0.2f;
131 return v - (
v + 1.0f) *
expf(-rand * phase_log);
137 return 1.0f /
sqrtf(1.0f -
powf(alpha, 2.44294f - 0.0215813f * alpha + 0.578637f / alpha));
148 return dir.
x * T + dir.
y *
B + dir.
z *
D;
160 return hit ?
T : sigma_t *
T;
165# define SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL 9
189 ray.self.object = object;
190 ray.self.prim = prim;
203 subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput);
214 const float diffusion_length = diffusion_length_dwivedi(
reduce_max(alpha));
216 if (diffusion_length == 1.0f) {
224 const float phase_log =
logf((diffusion_length + 1.0f) / (diffusion_length - 1.0f));
231 bool have_opposite_interface =
false;
232 float opposite_distance = 0.0f;
236 const float guided_fraction = 1.0f -
fmaxf(0.5f,
powf(
fabsf(anisotropy), 0.125f));
238# ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
239 Spectrum sigma_s_star = sigma_s * (1.0f - anisotropy);
240 Spectrum sigma_t_star = sigma_t - sigma_s + sigma_s_star;
243 const float anisotropy_org = anisotropy;
244 const float guided_fraction_org = guided_fraction;
251# ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
253 float anisotropy, guided_fraction;
255 if (bounce <= SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL) {
256 anisotropy = anisotropy_org;
257 guided_fraction = guided_fraction_org;
258 sigma_t = sigma_t_org;
259 sigma_s = sigma_s_org;
263 guided_fraction = 0.75f;
264 sigma_t = sigma_t_star;
265 sigma_s = sigma_s_star;
278 float backward_fraction = 0.0f;
279 float forward_pdf_factor = 0.0f;
280 float forward_stretching = 1.0f;
281 float backward_pdf_factor = 0.0f;
282 float backward_stretching = 1.0f;
294 bool guide_backward =
false;
295 if (have_opposite_interface) {
299 float x =
clamp(
dot(ray.P -
P, -
N), 0.0f, opposite_distance);
300 backward_fraction = 1.0f /
301 (1.0f +
expf((opposite_distance - 2.0f * x) / diffusion_length));
311 cos_theta = sample_phase_dwivedi(diffusion_length, phase_log, rand_scatter.
x);
314 if (guide_backward) {
333 forward_pdf_factor = M_1_2PI_F * eval_phase_dwivedi(diffusion_length, phase_log,
cos_theta) /
335 backward_pdf_factor = M_1_2PI_F *
336 eval_phase_dwivedi(diffusion_length, phase_log, -
cos_theta) / hg_pdf;
341 forward_stretching = (1.0f -
cos_theta / diffusion_length);
342 backward_stretching = (1.0f +
cos_theta / diffusion_length);
344 sample_sigma_t *= guide_backward ? backward_stretching : forward_stretching;
349 float t = -
logf(1.0f - randt) / sample_sigma_t;
364 scene_intersect_local<true>(kg, &ray, &ss_isect,
object,
NULL, 1);
365 hit = (ss_isect.num_hits > 0);
368 ray.tmax = ss_isect.hits[0].t;
374 have_opposite_interface =
true;
375 opposite_distance =
dot(ray.P + ray.tmax * ray.D -
P, -
N);
391 Spectrum pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance);
394 Spectrum guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit,
NULL);
396 if (have_opposite_interface) {
399 Spectrum back_pdf = subsurface_random_walk_pdf(
400 backward_stretching * sigma_t, t, hit,
NULL);
402 guided_pdf * forward_pdf_factor, back_pdf * backward_pdf_factor, backward_fraction);
406 guided_pdf *= forward_pdf_factor;
410 pdf =
mix(pdf, guided_pdf, guided_fraction);
416 throughput *= (hit ? transmittance : sigma_s * transmittance) /
dot(channel_pdf, pdf);
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device_inline float cos_theta(const float3 w)
ccl_device_inline float sin_theta(const float3 w)
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define kernel_assert(cond)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define ccl_device_forceinline
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float differential_zero_compact()
#define VOLUME_THROUGHPUT_EPSILON
ccl_device int volume_sample_channel(Spectrum albedo, Spectrum throughput, ccl_private float *rand, ccl_private Spectrum *pdf)
ccl_device float volume_channel_get(Spectrum value, int channel)
ccl_device Spectrum volume_color_transmittance(Spectrum sigma, float t)
ccl_device_forceinline void guiding_record_bssrdf_bounce(KernelGlobals kg, IntegratorState state, const float pdf, const float3 N, const float3 wo, const Spectrum weight, const Spectrum albedo)
@ PRNG_SUBSURFACE_COLOR_CHANNEL
@ PRNG_SUBSURFACE_GUIDE_STRATEGY
@ PRNG_SUBSURFACE_SCATTER_DISTANCE
@ PRNG_SUBSURFACE_GUIDE_DIRECTION
#define BSSRDF_MAX_BOUNCES
ccl_device_inline float reduce_max(const float2 a)
ccl_device_inline float reduce_min(const float2 a)
ccl_device_inline float path_state_rng_1D(KernelGlobals kg, ccl_private const RNGState *rng_state, const int dimension)
ccl_device_inline float2 path_state_rng_2D(KernelGlobals kg, ccl_private const RNGState *rng_state, const int dimension)
ccl_device_inline void path_state_rng_scramble(ccl_private RNGState *rng_state, const int seed)
IntegratorStateCPU *ccl_restrict IntegratorState
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
#define INTEGRATOR_STATE(state, nested_struct, member)
#define FOREACH_SPECTRUM_CHANNEL(counter)
#define GET_SPECTRUM_CHANNEL(v, i)
SPECTRUM_DATA_TYPE Spectrum
ccl_device_inline float sin_from_cos(const float c)
ccl_device_inline bool isfinite_safe(float f)
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
ccl_device_inline Spectrum safe_divide_color(Spectrum a, Spectrum b)
ccl_device_inline int clamp(int a, int mn, int mx)
ccl_device float phase_henyey_greenstein(float cos_theta, float g)
ccl_device float3 phase_henyey_greenstein_sample(float3 D, float g, float2 rand, ccl_private float *pdf)