diff options
author | Andrii Symkin <pembem22> | 2022-07-29 14:41:37 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2022-08-09 17:49:34 +0300 |
commit | d832d993c5b47b0de7ca24914ad9c064607830c7 (patch) | |
tree | 889b7cd9f135a40cbaccdb4537c8de1faa1c562f /intern/cycles/kernel/integrator | |
parent | 7921faa6519b9eb9062269b5d9c003c64ead2b8b (diff) |
Cycles: add new Spectrum and PackedSpectrum types
These replace float3 and packed_float3 in various places in the kernel where a
spectral color representation will be used in the future. That representation
will require more than 3 channels and conversion to from/RGB. The kernel code
was refactored to remove the assumption that Spectrum and RGB colors are the
same thing.
There are no functional changes, Spectrum is still a float3 and the conversion
functions are no-ops.
Differential Revision: https://developer.blender.org/D15535
Diffstat (limited to 'intern/cycles/kernel/integrator')
-rw-r--r-- | intern/cycles/kernel/integrator/mnee.h | 10 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/path_state.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_background.h | 20 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_light.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_shadow.h | 14 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_surface.h | 30 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_volume.h | 125 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shader_eval.h | 87 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shadow_catcher.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shadow_state_template.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/state_template.h | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/subsurface.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/subsurface_disk.h | 14 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/subsurface_random_walk.h | 87 |
14 files changed, 211 insertions, 214 deletions
diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h index aa72b93c9d2..98968400d0a 100644 --- a/intern/cycles/kernel/integrator/mnee.h +++ b/intern/cycles/kernel/integrator/mnee.h @@ -634,9 +634,9 @@ mnee_sample_bsdf_dh(ClosureType type, float alpha_x, float alpha_y, float sample * We assume here that the pdf (in half-vector measure) is the same as * the one calculation when sampling the microfacet normals from the * specular chain above: this allows us to simplify the bsdf weight */ -ccl_device_forceinline float3 mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure, - float3 wi, - float3 wo) +ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure, + float3 wi, + float3 wo) { ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)closure; @@ -835,7 +835,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, 1; INTEGRATOR_STATE_WRITE(state, path, bounce) = bounce + vertex_count; - float3 light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time); + Spectrum light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time); bsdf_eval_mul(throughput, light_eval / ls->pdf); /* Generalized geometry term. */ @@ -924,7 +924,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, /* Evaluate product term inside eq.6 at solution interface. vi * divided by corresponding sampled pdf: * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| */ - float3 bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo); + Spectrum bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo); bsdf_eval_mul(throughput, bsdf_contribution); } diff --git a/intern/cycles/kernel/integrator/path_state.h b/intern/cycles/kernel/integrator/path_state.h index b09bc117d78..5ec94b934ca 100644 --- a/intern/cycles/kernel/integrator/path_state.h +++ b/intern/cycles/kernel/integrator/path_state.h @@ -54,7 +54,7 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg, INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = 0.0f; INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = FLT_MAX; INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = 1.0f; - INTEGRATOR_STATE_WRITE(state, path, throughput) = make_float3(1.0f, 1.0f, 1.0f); + INTEGRATOR_STATE_WRITE(state, path, throughput) = one_spectrum(); #ifdef __MNEE__ INTEGRATOR_STATE_WRITE(state, path, mnee) = 0; @@ -74,7 +74,7 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg, #ifdef __DENOISING_FEATURES__ if (kernel_data.kernel_features & KERNEL_FEATURE_DENOISING) { INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_DENOISING_FEATURES; - INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) = one_float3(); + INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) = one_spectrum(); } #endif } diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h index a7edfffd175..57d060d58df 100644 --- a/intern/cycles/kernel/integrator/shade_background.h +++ b/intern/cycles/kernel/integrator/shade_background.h @@ -10,9 +10,9 @@ CCL_NAMESPACE_BEGIN -ccl_device float3 integrator_eval_background_shader(KernelGlobals kg, - IntegratorState state, - ccl_global float *ccl_restrict render_buffer) +ccl_device Spectrum integrator_eval_background_shader(KernelGlobals kg, + IntegratorState state, + ccl_global float *ccl_restrict render_buffer) { #ifdef __BACKGROUND__ const int shader = kernel_data.background.surface_shader; @@ -26,11 +26,11 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg, ((shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) || ((shader & SHADER_EXCLUDE_CAMERA) && (path_flag & PATH_RAY_CAMERA)) || ((shader & SHADER_EXCLUDE_SCATTER) && (path_flag & PATH_RAY_VOLUME_SCATTER))) - return zero_float3(); + return zero_spectrum(); } /* Use fast constant background color if available. */ - float3 L = zero_float3(); + Spectrum L = zero_spectrum(); if (!shader_constant_emission_eval(kg, shader, &L)) { /* Evaluate background shader. */ @@ -73,7 +73,7 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg, return L; #else - return make_float3(0.8f, 0.8f, 0.8f); + return make_spectrum(0.8f); #endif } @@ -117,8 +117,8 @@ ccl_device_inline void integrate_background(KernelGlobals kg, #endif /* __MNEE__ */ /* Evaluate background shader. */ - float3 L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) : - zero_float3(); + Spectrum L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) : + zero_spectrum(); /* When using the ao bounces approximation, adjust background * shader intensity with ao factor. */ @@ -169,7 +169,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, /* TODO: does aliasing like this break automatic SoA in CUDA? */ ShaderDataTinyStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); + Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); if (is_zero(light_eval)) { return; } @@ -184,7 +184,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, } /* Write to render buffer. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_accum_emission( kg, state, throughput * light_eval, render_buffer, kernel_data.background.lightgroup); } diff --git a/intern/cycles/kernel/integrator/shade_light.h b/intern/cycles/kernel/integrator/shade_light.h index 910e3383f51..ac9d1415abb 100644 --- a/intern/cycles/kernel/integrator/shade_light.h +++ b/intern/cycles/kernel/integrator/shade_light.h @@ -51,7 +51,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg, /* TODO: does aliasing like this break automatic SoA in CUDA? */ ShaderDataTinyStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); + Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); if (is_zero(light_eval)) { return; } @@ -66,7 +66,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg, } /* Write to render buffer. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_accum_emission(kg, state, throughput * light_eval, render_buffer, ls.group); } diff --git a/intern/cycles/kernel/integrator/shade_shadow.h b/intern/cycles/kernel/integrator/shade_shadow.h index 4b002a47bee..a52706a77f1 100644 --- a/intern/cycles/kernel/integrator/shade_shadow.h +++ b/intern/cycles/kernel/integrator/shade_shadow.h @@ -15,9 +15,9 @@ ccl_device_inline bool shadow_intersections_has_remaining(const uint num_hits) } #ifdef __TRANSPARENT_SHADOWS__ -ccl_device_inline float3 integrate_transparent_surface_shadow(KernelGlobals kg, - IntegratorShadowState state, - const int hit) +ccl_device_inline Spectrum integrate_transparent_surface_shadow(KernelGlobals kg, + IntegratorShadowState state, + const int hit) { PROFILING_INIT(kg, PROFILING_SHADE_SHADOW_SURFACE); @@ -58,7 +58,7 @@ ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg, IntegratorShadowState state, const int hit, const int num_recorded_hits, - ccl_private float3 *ccl_restrict + ccl_private Spectrum *ccl_restrict throughput) { PROFILING_INIT(kg, PROFILING_SHADE_SHADOW_VOLUME); @@ -100,7 +100,7 @@ ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg, if (hit < num_recorded_hits || !shadow_intersections_has_remaining(num_hits)) { # ifdef __VOLUME__ if (!integrator_state_shadow_volume_stack_is_empty(kg, state)) { - float3 throughput = INTEGRATOR_STATE(state, shadow_path, throughput); + Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput); integrate_transparent_volume_shadow(kg, state, hit, num_recorded_hits, &throughput); if (is_zero(throughput)) { return true; @@ -113,8 +113,8 @@ ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg, /* Surface shaders. */ if (hit < num_recorded_hits) { - const float3 shadow = integrate_transparent_surface_shadow(kg, state, hit); - const float3 throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow; + const Spectrum shadow = integrate_transparent_surface_shadow(kg, state, hit); + const Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow; if (is_zero(throughput)) { return true; } diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index 70b20a93b6a..986f7f622fb 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -42,11 +42,11 @@ ccl_device_forceinline bool integrate_surface_holdout(KernelGlobals kg, if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) && (path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { - const float3 holdout_weight = shader_holdout_apply(kg, sd); - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum holdout_weight = shader_holdout_apply(kg, sd); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); const float transparent = average(holdout_weight * throughput); kernel_accum_holdout(kg, state, path_flag, transparent, render_buffer); - if (isequal(holdout_weight, one_float3())) { + if (isequal(holdout_weight, one_spectrum())) { return false; } } @@ -65,7 +65,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); /* Evaluate emissive closure. */ - float3 L = shader_emissive_eval(sd); + Spectrum L = shader_emissive_eval(sd); # ifdef __HAIR__ if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && @@ -84,7 +84,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, L *= mis_weight; } - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_accum_emission( kg, state, throughput * L, render_buffer, object_lightgroup(kg, sd->object)); } @@ -161,7 +161,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, else # endif /* __MNEE__ */ { - const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); + const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); if (is_zero(light_eval)) { return; } @@ -211,11 +211,12 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, /* Copy state from main path to shadow path. */ uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag); shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0; - const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) * + bsdf_eval_sum(&bsdf_eval); if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { - packed_float3 pass_diffuse_weight; - packed_float3 pass_glossy_weight; + PackedSpectrum pass_diffuse_weight; + PackedSpectrum pass_glossy_weight; if (shadow_flag & PATH_RAY_ANY_PASS) { /* Indirect bounce, use weights from earlier surface or volume bounce. */ @@ -225,8 +226,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, else { /* Direct light, use BSDFs at this bounce. */ shadow_flag |= PATH_RAY_SURFACE_PASS; - pass_diffuse_weight = packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval)); - pass_glossy_weight = packed_float3(bsdf_eval_pass_glossy_weight(&bsdf_eval)); + pass_diffuse_weight = PackedSpectrum(bsdf_eval_pass_diffuse_weight(&bsdf_eval)); + pass_glossy_weight = PackedSpectrum(bsdf_eval_pass_glossy_weight(&bsdf_eval)); } INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight; @@ -338,7 +339,7 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce( } /* Update throughput. */ - float3 throughput = INTEGRATOR_STATE(state, path, throughput); + Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); throughput *= bsdf_eval_sum(&bsdf_eval) / bsdf_pdf; INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput; @@ -410,7 +411,7 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); float3 ao_N; - const float3 ao_weight = shader_bsdf_ao( + const Spectrum ao_weight = shader_bsdf_ao( kg, sd, kernel_data.integrator.ao_additive_factor, &ao_N); float3 ao_D; @@ -450,7 +451,8 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce); const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce); uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag) | PATH_RAY_SHADOW_FOR_AO; - const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * shader_bsdf_alpha(kg, sd); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) * + shader_bsdf_alpha(kg, sd); INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE( state, path, render_pixel_index); diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index 4aab097a7d8..0d35011c359 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -29,13 +29,13 @@ typedef enum VolumeIntegrateEvent { typedef struct VolumeIntegrateResult { /* Throughput and offset for direct light scattering. */ bool direct_scatter; - float3 direct_throughput; + Spectrum direct_throughput; float direct_t; ShaderVolumePhases direct_phases; /* Throughput and offset for indirect light scattering. */ bool indirect_scatter; - float3 indirect_throughput; + Spectrum indirect_throughput; float indirect_t; ShaderVolumePhases indirect_phases; } VolumeIntegrateResult; @@ -52,16 +52,16 @@ typedef struct VolumeIntegrateResult { * sigma_t = sigma_a + sigma_s */ typedef struct VolumeShaderCoefficients { - float3 sigma_t; - float3 sigma_s; - float3 emission; + Spectrum sigma_t; + Spectrum sigma_s; + Spectrum emission; } VolumeShaderCoefficients; /* Evaluate shader to get extinction coefficient at P. */ ccl_device_inline bool shadow_volume_shader_sample(KernelGlobals kg, IntegratorShadowState state, ccl_private ShaderData *ccl_restrict sd, - ccl_private float3 *ccl_restrict extinction) + ccl_private Spectrum *ccl_restrict extinction) { VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i)) shader_eval_volume<true>(kg, state, sd, PATH_RAY_SHADOW, volume_read_lambda_pass); @@ -89,9 +89,10 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals kg, return false; } - coeff->sigma_s = zero_float3(); - coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction : zero_float3(); - coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background : zero_float3(); + coeff->sigma_s = zero_spectrum(); + coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction : + zero_spectrum(); + coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background : zero_spectrum(); if (sd->flag & SD_SCATTER) { for (int i = 0; i < sd->num_closure; i++) { @@ -162,9 +163,9 @@ ccl_device_forceinline void volume_step_init(KernelGlobals kg, ccl_device void volume_shadow_homogeneous(KernelGlobals kg, IntegratorState state, ccl_private Ray *ccl_restrict ray, ccl_private ShaderData *ccl_restrict sd, - ccl_global float3 *ccl_restrict throughput) + ccl_global Spectrum *ccl_restrict throughput) { - float3 sigma_t = zero_float3(); + Spectrum sigma_t = zero_spectrum(); if (shadow_volume_shader_sample(kg, state, sd, &sigma_t)) { *throughput *= volume_color_transmittance(sigma_t, ray->tmax - ray->tmin); @@ -178,14 +179,14 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, IntegratorShadowState state, ccl_private Ray *ccl_restrict ray, ccl_private ShaderData *ccl_restrict sd, - ccl_private float3 *ccl_restrict throughput, + ccl_private Spectrum *ccl_restrict throughput, const float object_step_size) { /* Load random number state. */ RNGState rng_state; shadow_path_state_rng_load(state, &rng_state); - float3 tp = *throughput; + Spectrum tp = *throughput; /* Prepare for stepping. * For shadows we do not offset all segments, since the starting point is @@ -207,7 +208,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, /* compute extinction at the start */ float t = ray->tmin; - float3 sum = zero_float3(); + Spectrum sum = zero_spectrum(); for (int i = 0; i < max_steps; i++) { /* advance to new position */ @@ -215,7 +216,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, float dt = new_t - t; float3 new_P = ray->P + ray->D * (t + dt * step_shade_offset); - float3 sigma_t = zero_float3(); + Spectrum sigma_t = zero_spectrum(); /* compute attenuation over segment */ sd->P = new_P; @@ -228,8 +229,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, tp = *throughput * exp(sum); /* stop if nearly all light is blocked */ - if (tp.x < VOLUME_THROUGHPUT_EPSILON && tp.y < VOLUME_THROUGHPUT_EPSILON && - tp.z < VOLUME_THROUGHPUT_EPSILON) + if (reduce_max(tp) < VOLUME_THROUGHPUT_EPSILON) break; } } @@ -334,22 +334,22 @@ ccl_device float volume_equiangular_cdf(ccl_private const Ray *ccl_restrict ray, /* Distance sampling */ ccl_device float volume_distance_sample(float max_t, - float3 sigma_t, + Spectrum sigma_t, int channel, float xi, - ccl_private float3 *transmittance, - ccl_private float3 *pdf) + ccl_private Spectrum *transmittance, + ccl_private Spectrum *pdf) { /* xi is [0, 1[ so log(0) should never happen, division by zero is * avoided because sample_sigma_t > 0 when SD_SCATTER is set */ float sample_sigma_t = volume_channel_get(sigma_t, channel); - float3 full_transmittance = volume_color_transmittance(sigma_t, max_t); + Spectrum full_transmittance = volume_color_transmittance(sigma_t, max_t); float sample_transmittance = volume_channel_get(full_transmittance, channel); float sample_t = min(max_t, -logf(1.0f - xi * (1.0f - sample_transmittance)) / sample_sigma_t); *transmittance = volume_color_transmittance(sigma_t, sample_t); - *pdf = safe_divide_color(sigma_t * *transmittance, one_float3() - full_transmittance); + *pdf = safe_divide_color(sigma_t * *transmittance, one_spectrum() - full_transmittance); /* todo: optimization: when taken together with hit/miss decision, * the full_transmittance cancels out drops out and xi does not @@ -358,33 +358,36 @@ ccl_device float volume_distance_sample(float max_t, return sample_t; } -ccl_device float3 volume_distance_pdf(float max_t, float3 sigma_t, float sample_t) +ccl_device Spectrum volume_distance_pdf(float max_t, Spectrum sigma_t, float sample_t) { - float3 full_transmittance = volume_color_transmittance(sigma_t, max_t); - float3 transmittance = volume_color_transmittance(sigma_t, sample_t); + Spectrum full_transmittance = volume_color_transmittance(sigma_t, max_t); + Spectrum transmittance = volume_color_transmittance(sigma_t, sample_t); - return safe_divide_color(sigma_t * transmittance, one_float3() - full_transmittance); + return safe_divide_color(sigma_t * transmittance, one_spectrum() - full_transmittance); } /* Emission */ -ccl_device float3 volume_emission_integrate(ccl_private VolumeShaderCoefficients *coeff, - int closure_flag, - float3 transmittance, - float t) +ccl_device Spectrum volume_emission_integrate(ccl_private VolumeShaderCoefficients *coeff, + int closure_flag, + Spectrum transmittance, + float t) { /* integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t * this goes to E * t as sigma_t goes to zero * * todo: we should use an epsilon to avoid precision issues near zero sigma_t */ - float3 emission = coeff->emission; + Spectrum emission = coeff->emission; if (closure_flag & SD_EXTINCTION) { - float3 sigma_t = coeff->sigma_t; + Spectrum sigma_t = coeff->sigma_t; - emission.x *= (sigma_t.x > 0.0f) ? (1.0f - transmittance.x) / sigma_t.x : t; - emission.y *= (sigma_t.y > 0.0f) ? (1.0f - transmittance.y) / sigma_t.y : t; - emission.z *= (sigma_t.z > 0.0f) ? (1.0f - transmittance.z) / sigma_t.z : t; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(emission, i) *= (GET_SPECTRUM_CHANNEL(sigma_t, i) > 0.0f) ? + (1.0f - GET_SPECTRUM_CHANNEL(transmittance, i)) / + GET_SPECTRUM_CHANNEL(sigma_t, i) : + t; + } } else emission *= t; @@ -419,14 +422,14 @@ ccl_device_forceinline void volume_integrate_step_scattering( ccl_private const Ray *ray, const float3 equiangular_light_P, ccl_private const VolumeShaderCoefficients &ccl_restrict coeff, - const float3 transmittance, + const Spectrum transmittance, ccl_private VolumeIntegrateState &ccl_restrict vstate, ccl_private VolumeIntegrateResult &ccl_restrict result) { /* Pick random color channel, we use the Veach one-sample * model with balance heuristic for the channels. */ - const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); - float3 channel_pdf; + const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); + Spectrum channel_pdf; const int channel = volume_sample_channel( albedo, result.indirect_throughput, vstate.rphase, &channel_pdf); @@ -435,7 +438,7 @@ ccl_device_forceinline void volume_integrate_step_scattering( if (result.direct_t >= vstate.tmin && result.direct_t <= vstate.tmax && vstate.equiangular_pdf > VOLUME_SAMPLE_PDF_CUTOFF) { const float new_dt = result.direct_t - vstate.tmin; - const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); + const Spectrum new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); result.direct_scatter = true; result.direct_throughput *= coeff.sigma_s * new_transmittance / vstate.equiangular_pdf; @@ -467,7 +470,7 @@ ccl_device_forceinline void volume_integrate_step_scattering( const float new_t = vstate.tmin + new_dt; /* transmittance and pdf */ - const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); + const Spectrum new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); const float distance_pdf = dot(channel_pdf, coeff.sigma_t * new_transmittance); if (vstate.distance_pdf * distance_pdf > VOLUME_SAMPLE_PDF_CUTOFF) { @@ -566,7 +569,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous( vstate.distance_pdf = 1.0f; /* Initialize volume integration result. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); result.direct_throughput = throughput; result.indirect_throughput = throughput; @@ -579,9 +582,9 @@ ccl_device_forceinline void volume_integrate_heterogeneous( # ifdef __DENOISING_FEATURES__ const bool write_denoising_features = (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_DENOISING_FEATURES); - float3 accum_albedo = zero_float3(); + Spectrum accum_albedo = zero_spectrum(); # endif - float3 accum_emission = zero_float3(); + Spectrum accum_emission = zero_spectrum(); for (int i = 0; i < max_steps; i++) { /* Advance to new position */ @@ -596,16 +599,16 @@ ccl_device_forceinline void volume_integrate_heterogeneous( /* Evaluate transmittance over segment. */ const float dt = (vstate.tmax - vstate.tmin); - const float3 transmittance = (closure_flag & SD_EXTINCTION) ? - volume_color_transmittance(coeff.sigma_t, dt) : - one_float3(); + const Spectrum transmittance = (closure_flag & SD_EXTINCTION) ? + volume_color_transmittance(coeff.sigma_t, dt) : + one_spectrum(); /* Emission. */ if (closure_flag & SD_EMISSION) { /* Only write emission before indirect light scatter position, since we terminate * stepping at that point if we have already found a direct light scatter position. */ if (!result.indirect_scatter) { - const float3 emission = volume_emission_integrate( + const Spectrum emission = volume_emission_integrate( &coeff, closure_flag, transmittance, dt); accum_emission += result.indirect_throughput * emission; } @@ -616,8 +619,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous( # ifdef __DENOISING_FEATURES__ /* Accumulate albedo for denoising features. */ if (write_denoising_features && (closure_flag & SD_SCATTER)) { - const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); - accum_albedo += result.indirect_throughput * albedo * (one_float3() - transmittance); + const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); + accum_albedo += result.indirect_throughput * albedo * (one_spectrum() - transmittance); } # endif @@ -634,7 +637,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous( /* Stop if nearly all light blocked. */ if (!result.indirect_scatter) { if (reduce_max(result.indirect_throughput) < VOLUME_THROUGHPUT_EPSILON) { - result.indirect_throughput = zero_float3(); + result.indirect_throughput = zero_spectrum(); break; } } @@ -715,7 +718,7 @@ ccl_device_forceinline void integrate_volume_direct_light( ccl_private const RNGState *ccl_restrict rng_state, const float3 P, ccl_private const ShaderVolumePhases *ccl_restrict phases, - ccl_private const float3 throughput, + ccl_private const Spectrum throughput, ccl_private LightSample *ccl_restrict ls) { PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_DIRECT_LIGHT); @@ -753,7 +756,7 @@ ccl_device_forceinline void integrate_volume_direct_light( * non-constant light sources. */ ShaderDataTinyStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, ls, sd->time); + const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, ls, sd->time); if (is_zero(light_eval)) { return; } @@ -796,11 +799,11 @@ ccl_device_forceinline void integrate_volume_direct_light( const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce); uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag); shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0; - const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval); + const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval); if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { - packed_float3 pass_diffuse_weight; - packed_float3 pass_glossy_weight; + PackedSpectrum pass_diffuse_weight; + PackedSpectrum pass_glossy_weight; if (shadow_flag & PATH_RAY_ANY_PASS) { /* Indirect bounce, use weights from earlier surface or volume bounce. */ @@ -810,8 +813,8 @@ ccl_device_forceinline void integrate_volume_direct_light( else { /* Direct light, no diffuse/glossy distinction needed for volumes. */ shadow_flag |= PATH_RAY_VOLUME_PASS; - pass_diffuse_weight = packed_float3(one_float3()); - pass_glossy_weight = packed_float3(zero_float3()); + pass_diffuse_weight = one_spectrum(); + pass_glossy_weight = zero_spectrum(); } INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight; @@ -898,13 +901,13 @@ ccl_device_forceinline bool integrate_volume_phase_scatter( INTEGRATOR_STATE_WRITE(state, isect, object) = sd->object; /* Update throughput. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf; + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf; INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase; if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { - INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3(); - INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3(); + INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum(); + INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum(); } /* Update path state */ diff --git a/intern/cycles/kernel/integrator/shader_eval.h b/intern/cycles/kernel/integrator/shader_eval.h index ed4d973e864..d9c14b25a4b 100644 --- a/intern/cycles/kernel/integrator/shader_eval.h +++ b/intern/cycles/kernel/integrator/shader_eval.h @@ -98,7 +98,7 @@ ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg, /* Filter out closures. */ if (kernel_data.integrator.filter_closures) { if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) { - sd->closure_emission_background = zero_float3(); + sd->closure_emission_background = zero_spectrum(); } if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) { @@ -231,7 +231,7 @@ ccl_device_inline float _shader_bsdf_multi_eval(KernelGlobals kg, if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { if (CLOSURE_IS_BSDF(sc->type) && !_shader_bsdf_exclude(sc->type, light_shader_flags)) { float bsdf_pdf = 0.0f; - float3 eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf); + Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf); if (bsdf_pdf != 0.0f) { bsdf_eval_accum(result_eval, sc->type, eval * sc->weight); @@ -259,7 +259,7 @@ ccl_device_inline ccl_private BsdfEval *bsdf_eval, const uint light_shader_flags) { - bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_float3()); + bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum()); return _shader_bsdf_multi_eval( kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags); @@ -309,11 +309,11 @@ ccl_device_inline ccl_private const ShaderClosure *shader_bsdf_bssrdf_pick( } /* Return weight for picked BSSRDF. */ -ccl_device_inline float3 +ccl_device_inline Spectrum shader_bssrdf_sample_weight(ccl_private const ShaderData *ccl_restrict sd, ccl_private const ShaderClosure *ccl_restrict bssrdf_sc) { - float3 weight = bssrdf_sc->weight; + Spectrum weight = bssrdf_sc->weight; if (sd->num_closure > 1) { float sum = 0.0f; @@ -346,7 +346,7 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals kg, kernel_assert(CLOSURE_IS_BSDF(sc->type)); int label; - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); *pdf = 0.0f; label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); @@ -385,16 +385,16 @@ ccl_device float shader_bsdf_average_roughness(ccl_private const ShaderData *sd) return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f; } -ccl_device float3 shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd) { if (sd->flag & SD_HAS_ONLY_VOLUME) { - return one_float3(); + return one_spectrum(); } else if (sd->flag & SD_TRANSPARENT) { return sd->closure_transparent_extinction; } else { - return zero_float3(); + return zero_spectrum(); } } @@ -406,7 +406,7 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private S if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) { sc->sample_weight = 0.0f; - sc->weight = zero_float3(); + sc->weight = zero_spectrum(); } } @@ -414,19 +414,18 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private S } } -ccl_device float3 shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd); + Spectrum alpha = one_spectrum() - shader_bsdf_transparency(kg, sd); - alpha = max(alpha, zero_float3()); - alpha = min(alpha, one_float3()); + alpha = saturate(alpha); return alpha; } -ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -438,9 +437,9 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const Shader return eval; } -ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -452,9 +451,9 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderD return eval; } -ccl_device float3 shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -479,12 +478,12 @@ ccl_device float3 shader_bsdf_average_normal(KernelGlobals kg, ccl_private const return (is_zero(N)) ? sd->N : normalize(N); } -ccl_device float3 shader_bsdf_ao(KernelGlobals kg, - ccl_private const ShaderData *sd, - const float ao_factor, - ccl_private float3 *N_) +ccl_device Spectrum shader_bsdf_ao(KernelGlobals kg, + ccl_private const ShaderData *sd, + const float ao_factor, + ccl_private float3 *N_) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); float3 N = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { @@ -525,15 +524,17 @@ ccl_device float3 shader_bssrdf_normal(ccl_private const ShaderData *sd) ccl_device bool shader_constant_emission_eval(KernelGlobals kg, int shader, - ccl_private float3 *eval) + ccl_private Spectrum *eval) { int shader_index = shader & SHADER_MASK; int shader_flag = kernel_data_fetch(shaders, shader_index).flags; if (shader_flag & SD_HAS_CONSTANT_EMISSION) { - *eval = make_float3(kernel_data_fetch(shaders, shader_index).constant_emission[0], - kernel_data_fetch(shaders, shader_index).constant_emission[1], - kernel_data_fetch(shaders, shader_index).constant_emission[2]); + const float3 emission_rgb = make_float3( + kernel_data_fetch(shaders, shader_index).constant_emission[0], + kernel_data_fetch(shaders, shader_index).constant_emission[1], + kernel_data_fetch(shaders, shader_index).constant_emission[2]); + *eval = rgb_to_spectrum(emission_rgb); return true; } @@ -543,39 +544,39 @@ ccl_device bool shader_constant_emission_eval(KernelGlobals kg, /* Background */ -ccl_device float3 shader_background_eval(ccl_private const ShaderData *sd) +ccl_device Spectrum shader_background_eval(ccl_private const ShaderData *sd) { if (sd->flag & SD_EMISSION) { return sd->closure_emission_background; } else { - return zero_float3(); + return zero_spectrum(); } } /* Emission */ -ccl_device float3 shader_emissive_eval(ccl_private const ShaderData *sd) +ccl_device Spectrum shader_emissive_eval(ccl_private const ShaderData *sd) { if (sd->flag & SD_EMISSION) { return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background; } else { - return zero_float3(); + return zero_spectrum(); } } /* Holdout */ -ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd) +ccl_device Spectrum shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd) { - float3 weight = zero_float3(); + Spectrum weight = zero_spectrum(); /* For objects marked as holdout, preserve transparency and remove all other * closures, replacing them with a holdout weight. */ if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) { - weight = one_float3() - sd->closure_transparent_extinction; + weight = one_spectrum() - sd->closure_transparent_extinction; for (int i = 0; i < sd->num_closure; i++) { ccl_private ShaderClosure *sc = &sd->closure[i]; @@ -587,7 +588,7 @@ ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData sd->flag &= ~(SD_CLOSURE_FLAGS - (SD_TRANSPARENT | SD_BSDF)); } else { - weight = one_float3(); + weight = one_spectrum(); } } else { @@ -642,12 +643,12 @@ ccl_device void shader_eval_surface(KernelGlobals kg, svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>(kg, state, sd, buffer, path_flag); #else if (sd->object == OBJECT_NONE) { - sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f); + sd->closure_emission_background = make_spectrum(0.8f); sd->flag |= SD_EMISSION; } else { ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( - sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f)); + sd, sizeof(DiffuseBsdf), make_spectrum(0.8f)); if (bsdf != NULL) { bsdf->N = sd->N; sd->flag |= bsdf_diffuse_setup(bsdf); @@ -676,7 +677,7 @@ ccl_device_inline float _shader_volume_phase_multi_eval( ccl_private const ShaderVolumeClosure *svc = &phases->closure[i]; float phase_pdf = 0.0f; - float3 eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf); + Spectrum eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf); if (phase_pdf != 0.0f) { bsdf_eval_accum(result_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); @@ -695,7 +696,7 @@ ccl_device float shader_volume_phase_eval(KernelGlobals kg, const float3 omega_in, ccl_private BsdfEval *phase_eval) { - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_float3()); + bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum()); return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f); } @@ -747,7 +748,7 @@ ccl_device int shader_volume_phase_sample(KernelGlobals kg, * depending on color channels, even if this is perhaps not a common case */ ccl_private const ShaderVolumeClosure *svc = &phases->closure[sampled]; int label; - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); *pdf = 0.0f; label = volume_phase_sample(sd, svc, randu, randv, &eval, omega_in, domega_in, pdf); @@ -770,7 +771,7 @@ ccl_device int shader_phase_sample_closure(KernelGlobals kg, ccl_private float *pdf) { int label; - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); *pdf = 0.0f; label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); diff --git a/intern/cycles/kernel/integrator/shadow_catcher.h b/intern/cycles/kernel/integrator/shadow_catcher.h index ff63625aceb..7103b6032ac 100644 --- a/intern/cycles/kernel/integrator/shadow_catcher.h +++ b/intern/cycles/kernel/integrator/shadow_catcher.h @@ -93,7 +93,7 @@ ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data( /* Since the split is done, the sample does not contribute to the matte, so accumulate it as * transparency to the matte. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3, average(throughput)); } diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h index c340467606d..3b490ecffdd 100644 --- a/intern/cycles/kernel/integrator/shadow_state_template.h +++ b/intern/cycles/kernel/integrator/shadow_state_template.h @@ -27,15 +27,15 @@ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, queued_kernel, KERNEL_FEATURE_PATH_T /* enum PathRayFlag */ KERNEL_STRUCT_MEMBER(shadow_path, uint32_t, flag, KERNEL_FEATURE_PATH_TRACING) /* Throughput. */ -KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, throughput, KERNEL_FEATURE_PATH_TRACING) +KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, throughput, KERNEL_FEATURE_PATH_TRACING) /* Throughput for shadow pass. */ KERNEL_STRUCT_MEMBER(shadow_path, - packed_float3, + PackedSpectrum, unshadowed_throughput, KERNEL_FEATURE_SHADOW_PASS | KERNEL_FEATURE_AO_ADDITIVE) /* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */ -KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) -KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) /* Number of intersections found by ray-tracing. */ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING) /* Light group. */ diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h index 5c2af131945..f4e280e4cb2 100644 --- a/intern/cycles/kernel/integrator/state_template.h +++ b/intern/cycles/kernel/integrator/state_template.h @@ -46,12 +46,12 @@ KERNEL_STRUCT_MEMBER(path, float, min_ray_pdf, KERNEL_FEATURE_PATH_TRACING) /* Continuation probability for path termination. */ KERNEL_STRUCT_MEMBER(path, float, continuation_probability, KERNEL_FEATURE_PATH_TRACING) /* Throughput. */ -KERNEL_STRUCT_MEMBER(path, packed_float3, throughput, KERNEL_FEATURE_PATH_TRACING) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, throughput, KERNEL_FEATURE_PATH_TRACING) /* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */ -KERNEL_STRUCT_MEMBER(path, packed_float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) -KERNEL_STRUCT_MEMBER(path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) /* Denoising. */ -KERNEL_STRUCT_MEMBER(path, packed_float3, denoising_feature_throughput, KERNEL_FEATURE_DENOISING) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, denoising_feature_throughput, KERNEL_FEATURE_DENOISING) /* Shader sorting. */ /* TODO: compress as uint16? or leave out entirely and recompute key in sorting code? */ KERNEL_STRUCT_MEMBER(path, uint32_t, shader_sort_key, KERNEL_FEATURE_PATH_TRACING) @@ -84,8 +84,8 @@ KERNEL_STRUCT_END(isect) /*************** Subsurface closure state for subsurface kernel ***************/ KERNEL_STRUCT_BEGIN(subsurface) -KERNEL_STRUCT_MEMBER(subsurface, packed_float3, albedo, KERNEL_FEATURE_SUBSURFACE) -KERNEL_STRUCT_MEMBER(subsurface, packed_float3, radius, KERNEL_FEATURE_SUBSURFACE) +KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, albedo, KERNEL_FEATURE_SUBSURFACE) +KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, radius, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_MEMBER(subsurface, float, anisotropy, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_MEMBER(subsurface, packed_float3, Ng, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_END(subsurface) diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index 2f96f215d8a..ee3a619f968 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -51,7 +51,7 @@ ccl_device int subsurface_bounce(KernelGlobals kg, PATH_RAY_SUBSURFACE_RANDOM_WALK); /* Compute weight, optionally including Fresnel from entry point. */ - float3 weight = shader_bssrdf_sample_weight(sd, sc); + Spectrum weight = shader_bssrdf_sample_weight(sd, sc); # ifdef __PRINCIPLED__ if (bssrdf->roughness != FLT_MAX) { path_flag |= PATH_RAY_SUBSURFACE_USE_FRESNEL; @@ -70,8 +70,8 @@ ccl_device int subsurface_bounce(KernelGlobals kg, if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { if (INTEGRATOR_STATE(state, path, bounce) == 0) { - INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3(); - INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3(); + INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum(); + INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum(); } } @@ -99,7 +99,7 @@ ccl_device void subsurface_shader_data_setup(KernelGlobals kg, sd->num_closure = 0; sd->num_closure_left = kernel_data.max_closures; - const float3 weight = one_float3(); + const Spectrum weight = one_spectrum(); # ifdef __PRINCIPLED__ if (path_flag & PATH_RAY_SUBSURFACE_USE_FRESNEL) { diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index 60b63c075a0..77763f702d8 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -9,11 +9,11 @@ CCL_NAMESPACE_BEGIN * http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf */ -ccl_device_inline float3 subsurface_disk_eval(const float3 radius, float disk_r, float r) +ccl_device_inline Spectrum subsurface_disk_eval(const Spectrum radius, float disk_r, float r) { - const float3 eval = bssrdf_eval(radius, r); + const Spectrum eval = bssrdf_eval(radius, r); const float pdf = bssrdf_pdf(radius, disk_r); - return (pdf > 0.0f) ? eval / pdf : zero_float3(); + return (pdf > 0.0f) ? eval / pdf : zero_spectrum(); } /* Subsurface scattering step, from a point on the surface to other @@ -37,7 +37,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); /* Read subsurface scattering parameters. */ - const float3 radius = INTEGRATOR_STATE(state, subsurface, radius); + const Spectrum radius = INTEGRATOR_STATE(state, subsurface, radius); /* Pick random axis in local frame and point on disk. */ float3 disk_N, disk_T, disk_B; @@ -108,7 +108,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, * traversal algorithm. */ sort_intersections_and_normals(ss_isect.hits, ss_isect.Ng, num_eval_hits); - float3 weights[BSSRDF_MAX_HITS]; /* TODO: zero? */ + Spectrum weights[BSSRDF_MAX_HITS]; /* TODO: zero? */ float sum_weights = 0.0f; for (int hit = 0; hit < num_eval_hits; hit++) { @@ -150,7 +150,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const float r = len(hit_P - P); /* Evaluate profiles. */ - const float3 weight = subsurface_disk_eval(radius, disk_r, r) * w; + const Spectrum weight = subsurface_disk_eval(radius, disk_r, r) * w; /* Store result. */ ss_isect.Ng[hit] = hit_Ng; @@ -167,7 +167,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, float partial_sum = 0.0f; for (int hit = 0; hit < num_eval_hits; hit++) { - const float3 weight = weights[hit]; + const Spectrum weight = weights[hit]; const float sample_weight = average(fabs(weight)); float next_sum = partial_sum + sample_weight; diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h index e43bbb3c50a..9c67d909bd4 100644 --- a/intern/cycles/kernel/integrator/subsurface_random_walk.h +++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h @@ -65,19 +65,20 @@ ccl_device void subsurface_random_walk_remap(const float albedo, *sigma_t = sigma_t_prime / (1.0f - g); } -ccl_device void subsurface_random_walk_coefficients(const float3 albedo, - const float3 radius, +ccl_device void subsurface_random_walk_coefficients(const Spectrum albedo, + const Spectrum radius, const float anisotropy, - ccl_private float3 *sigma_t, - ccl_private float3 *alpha, - ccl_private float3 *throughput) + ccl_private Spectrum *sigma_t, + ccl_private Spectrum *alpha, + ccl_private Spectrum *throughput) { - float sigma_t_x, sigma_t_y, sigma_t_z; - float alpha_x, alpha_y, alpha_z; - - subsurface_random_walk_remap(albedo.x, radius.x, anisotropy, &sigma_t_x, &alpha_x); - subsurface_random_walk_remap(albedo.y, radius.y, anisotropy, &sigma_t_y, &alpha_y); - subsurface_random_walk_remap(albedo.z, radius.z, anisotropy, &sigma_t_z, &alpha_z); + FOREACH_SPECTRUM_CHANNEL (i) { + subsurface_random_walk_remap(GET_SPECTRUM_CHANNEL(albedo, i), + GET_SPECTRUM_CHANNEL(radius, i), + anisotropy, + &GET_SPECTRUM_CHANNEL(*sigma_t, i), + &GET_SPECTRUM_CHANNEL(*alpha, i)); + } /* Throughput already contains closure weight at this point, which includes the * albedo, as well as closure mixing and Fresnel weights. Divide out the albedo @@ -88,21 +89,12 @@ ccl_device void subsurface_random_walk_coefficients(const float3 albedo, * infinite phase functions. To avoid a sharp discontinuity as we go from * such values to 0.0, increase alpha and reduce the throughput to compensate. */ const float min_alpha = 0.2f; - if (alpha_x < min_alpha) { - (*throughput).x *= alpha_x / min_alpha; - alpha_x = min_alpha; - } - if (alpha_y < min_alpha) { - (*throughput).y *= alpha_y / min_alpha; - alpha_y = min_alpha; - } - if (alpha_z < min_alpha) { - (*throughput).z *= alpha_z / min_alpha; - alpha_z = min_alpha; + FOREACH_SPECTRUM_CHANNEL (i) { + if (GET_SPECTRUM_CHANNEL(*alpha, i) < min_alpha) { + GET_SPECTRUM_CHANNEL(*throughput, i) *= GET_SPECTRUM_CHANNEL(*alpha, i) / min_alpha; + GET_SPECTRUM_CHANNEL(*alpha, i) = min_alpha; + } } - - *sigma_t = make_float3(sigma_t_x, sigma_t_y, sigma_t_z); - *alpha = make_float3(alpha_x, alpha_y, alpha_z); } /* References for Dwivedi sampling: @@ -151,12 +143,12 @@ ccl_device_forceinline float3 direction_from_cosine(float3 D, float cos_theta, f return dir.x * T + dir.y * B + dir.z * D; } -ccl_device_forceinline float3 subsurface_random_walk_pdf(float3 sigma_t, - float t, - bool hit, - ccl_private float3 *transmittance) +ccl_device_forceinline Spectrum subsurface_random_walk_pdf(Spectrum sigma_t, + float t, + bool hit, + ccl_private Spectrum *transmittance) { - float3 T = volume_color_transmittance(sigma_t, t); + Spectrum T = volume_color_transmittance(sigma_t, t); if (transmittance) { *transmittance = T; } @@ -207,14 +199,14 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* Convert subsurface to volume coefficients. * The single-scattering albedo is named alpha to avoid confusion with the surface albedo. */ - const float3 albedo = INTEGRATOR_STATE(state, subsurface, albedo); - const float3 radius = INTEGRATOR_STATE(state, subsurface, radius); + const Spectrum albedo = INTEGRATOR_STATE(state, subsurface, albedo); + const Spectrum radius = INTEGRATOR_STATE(state, subsurface, radius); const float anisotropy = INTEGRATOR_STATE(state, subsurface, anisotropy); - float3 sigma_t, alpha; - float3 throughput = INTEGRATOR_STATE_WRITE(state, path, throughput); + Spectrum sigma_t, alpha; + Spectrum throughput = INTEGRATOR_STATE_WRITE(state, path, throughput); subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput); - float3 sigma_s = sigma_t * alpha; + Spectrum sigma_s = sigma_t * alpha; /* 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 @@ -249,10 +241,10 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, const float guided_fraction = 1.0f - fmaxf(0.5f, powf(fabsf(anisotropy), 0.125f)); #ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL - float3 sigma_s_star = sigma_s * (1.0f - anisotropy); - float3 sigma_t_star = sigma_t - sigma_s + sigma_s_star; - float3 sigma_t_org = sigma_t; - float3 sigma_s_org = sigma_s; + Spectrum sigma_s_star = sigma_s * (1.0f - anisotropy); + Spectrum sigma_t_star = sigma_t - sigma_s + sigma_s_star; + Spectrum sigma_t_org = sigma_t; + Spectrum sigma_s_org = sigma_s; const float anisotropy_org = anisotropy; const float guided_fraction_org = guided_fraction; #endif @@ -264,7 +256,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, #ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL // shadow with local variables according to depth float anisotropy, guided_fraction; - float3 sigma_s, sigma_t; + Spectrum sigma_s, sigma_t; if (bounce <= SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL) { anisotropy = anisotropy_org; guided_fraction = guided_fraction_org; @@ -281,7 +273,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* Sample color channel, use MIS with balance heuristic. */ float rphase = path_state_rng_1D(kg, &rng_state, PRNG_PHASE_CHANNEL); - float3 channel_pdf; + Spectrum channel_pdf; int channel = volume_sample_channel(alpha, throughput, rphase, &channel_pdf); float sample_sigma_t = volume_channel_get(sigma_t, channel); float randt = path_state_rng_1D(kg, &rng_state, PRNG_SCATTER_DISTANCE); @@ -399,16 +391,17 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* Advance to new scatter location. */ ray.P += t * ray.D; - float3 transmittance; - float3 pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance); + Spectrum transmittance; + Spectrum pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance); if (bounce > 0) { /* Compute PDF just like we do for classic sampling, but with the stretched sigma_t. */ - float3 guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL); + Spectrum guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL); if (have_opposite_interface) { /* First step of MIS: Depending on geometry we might have two methods for guided * sampling, so perform MIS between them. */ - float3 back_pdf = subsurface_random_walk_pdf(backward_stretching * sigma_t, t, hit, NULL); + Spectrum back_pdf = subsurface_random_walk_pdf( + backward_stretching * sigma_t, t, hit, NULL); guided_pdf = mix( guided_pdf * forward_pdf_factor, back_pdf * backward_pdf_factor, backward_fraction); } @@ -430,9 +423,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* If we hit the surface, we are done. */ break; } - else if (throughput.x < VOLUME_THROUGHPUT_EPSILON && - throughput.y < VOLUME_THROUGHPUT_EPSILON && - throughput.z < VOLUME_THROUGHPUT_EPSILON) { + else if (reduce_max(throughput) < VOLUME_THROUGHPUT_EPSILON) { /* Avoid unnecessary work and precision issue when throughput gets really small. */ break; } |